- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在posts
表中,有title
、content
等属性。我可以获取 *sql.Rows
类型的数据并将它们传递给 View
posts, err := db.Query("SELECT id, title FROM posts WHERE id = 1")
和
err = tpl.ExecuteTemplate(w, "index.gohtml", posts)
但我无法在 View 中显示 title
值。这是我的代码。
index.go
package main
import (
"net/http"
"fmt"
"log"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func index(w http.ResponseWriter, r *http.Request) {
db, err := sql.Open("mysql", "root:****@/database")
if err != nil {
panic(err.Error())
}
defer db.Close()
posts, err := db.Query("SELECT id, title FROM posts WHERE id = 1")
var id int
var title string
for posts.Next() {
err = posts.Scan(&id, &title)
if err != nil {
panic(err.Error())
}
}
fmt.Println(posts)
defer posts.Close()
err = tpl.ExecuteTemplate(w, "index.gohtml", posts)
if err != nil {
log.Println(err)
}
}
index.gohtml
<h1>Awesome Posts</h1>
{{$posts := .}}
<p>{{$posts}}</p>
最佳答案
您的代码中有一些错误,我认为您误解了如何使用 sql
包提取数据。
正如 Flimzy 在评论中所说,您应该传递一个适当的上下文结构,其中包含您的 ID 和 Title 值。
如果您检查 docs for sql.Rows您将看到如何从查询中提取每一行的数据...事实上,您已经知道如何获取行和列值 - 通过使用 Next()
和 Scan()
方法。但这不应该由 HTML 模板中的代码完成,它应该将结果存储在传递给模板的某个变量中。
对您的问题的快速回答是更改将值传递到模板的方式并修改模板。当您声明 id
和 title
变量时,您应该将它们传递给模板:
err = tpl.ExecuteTemplate(w, "index.gohtml", map[string]interface{}{"ID": id,"Title": title})
if err != nil {
log.Println(err)
}
<h1>Awesome Posts</h1>
<p>{{.ID}} - {{.Title}}</p>
更好的解决方案是拥有一个包含帖子所有属性的结构,并使用它扫描
进入。
type Post struct{
ID int
Title string
}
...
var p Post
...
_ = rows.Scan(&p)
但是,存储查询结果的方式还有另一个问题。您正在使用 db.Query
返回单行 - 这是一个假设,因为您有 WHERE ID=1
。如果您希望只返回一个帖子,则使用 QueryRow 方法:(注意为了简单起见,您可以链接 Scan 方法)
var p Post
// error handling removed for brevity
_ = db.QueryRow("SELECT id, title FROM posts WHERE id = 1").Scan(&p)
_ = tpl.ExecuteTemplate(w, "index.gohtml", p)
但是,如果您希望检索多个帖子(并且您只是为了简单起见而添加了 where 子句),那么您需要将 Scan
放入 Post
结构中, 并追加到 Posts
的 slice 中。
rows, _ := db.Query("SELECT id, title FROM posts")
defer rows.Close()
var posts []Post
for rows.Next() {
var p Post
_ = posts.Scan(&id, &p) // you should handle error here.
posts = append(posts, p)
}
if err = tpl.ExecuteTemplate(w, "index.gohtml", posts); err!=nil{
log.Println(err)
}
您不应该在 HTTP 处理程序中创建到数据库的连接。一种方法是使用一个全局变量来保存连接。具有嵌入式连接的结构可以工作和/或也可以将连接抽象到一个包中。
/db/db.go
package db
import (
"database/sql"
// MYSQL driver
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
// Open handles the opening of the DB
func Open(connstr string) (err error) {
db, err = sql.Open("mysql", connstr)
if err != nil {
return err
}
return nil
}
// Close handles the closing of the DB
func Close() error {
return db.Close()
}
/db/posts.go
package db
// Post model
type Post struct {
ID uint
Title string
Body string
}
const (
getPosts = `SELECT id, title, body FROM posts`
getAPost = `SELECT id, title, body FROM posts WHERE id=?`
)
// GetPosts will return all posts from the DB
func GetPosts() ([]Post, error) {
rows, err := db.Query(getPosts)
if err != nil {
return nil, err
}
var posts []Post
for rows.Next() {
var p Post
if err := rows.Scan(&p.ID, &p.Title, &p.Body); err != nil {
return nil, err
}
posts = append(posts, p)
}
return posts, nil
}
// GetPost will return single post identified by ID from the DB
func GetPost(id uint) (Post, error) {
var p Post
if err := db.QueryRow(getAPost, id).Scan(&p.ID, &p.Title, &p.Body); err != nil {
return p, err
}
return p, nil
}
main.go
import (
"chilledoj/sopost/db" // this is the absolute path to the db folder
"html/template"
"log"
"net/http"
"strconv"
"flag"
"github.com/gorilla/mux"
)
var dbconn string
func init() {
flag.StringVar(&dbconn, "dbconn", "", "MYSQL DB Connection string")
flag.Parse()
}
func main() {
if dbconn == "" {
log.Fatal("DB Connection string not set")
}
if err := db.Open(dbconn); err != nil {
log.Fatal(err)
}
defer db.Close()
r := mux.NewRouter()
r.HandleFunc("/", indexHandler())
r.HandleFunc("/posts", postsHandler())
r.HandleFunc("/posts/{id}", postHandler())
if err := http.ListenAndServe(":8080", r); err != nil {
log.Panic(err)
}
}
var indexHandler = func() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`<h1>Welcome</h1><a href="/posts">Posts</a>`))
}
}
var postsHandler = func() http.HandlerFunc {
tmpl, err := template.New("posts").Parse(`<h1>Awesome Posts</h1>
<ul>{{range .}}
<li><a href="/posts/{{.ID}}">{{.Title}}</a></li>
{{end}}</ul>
<hr/>
<a href="/">Home</a>`)
if err != nil {
log.Panic(err)
}
return func(w http.ResponseWriter, r *http.Request) {
posts, err := db.GetPosts()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
err = tmpl.Execute(w, posts)
if err != nil {
log.Printf("There was a template Error.\n%v\n", err)
}
}
}
var postHandler = func() http.HandlerFunc {
tmpl, err := template.New("posts").Parse(`<h1>Awesome Posts</h1>
<h2>{{.Title}}</h2>
<p>{{.Body}}</p>
<hr/>
<a href="/">Home</a>
<a href="/posts">Posts</a>`)
if err != nil {
log.Panic(err)
}
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.ParseInt(vars["id"], 10, 32)
if err != nil {
http.NotFound(w, r)
return
}
post, err := db.GetPost(uint(id))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
tmpl.Execute(w, post)
}
}
运行以上使用
go run main.go -dbconn [dbuser]:[dbpass]@/[dbname]?parseTime=true
另一种方法是使用依赖注入(inject)并让一个函数接受数据库连接但返回一个http.HandlerFunc
。例如
var indexHandler = function (db *sql.DB) http.HandlerFunc{
return function(w http.ResponseWriter, r *http.Request){
// now have access to db
}
}
http.HandleFunc("/posts", indexHandler())
关于mysql - 如何从 View 中 *sql.Rows 类型的变量中获取值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51893641/
这个问题在这里已经有了答案: final keyword in method parameters [duplicate] (9 个回答) 关闭 8 年前。 在此示例中,声明 Object fina
我的目标:是通过我的函数更新字段获取选定值并使用函数输出值运行它。 问题:当我从列表中选择值时,它不会触发函数,也不会更新字段。 感谢您的帮助。 HTML 12 14 16 18 20 22 24
我有一本具有这种形式的字典: myDict = {'foo': bar, 'foobar baz': qux} 现在,我想拆分字典键中的空格,使其成为下一个键并获取值(重复)。 myDictRev1
vector a; vector b; int temp_holder; cout > temp_holder) a.push_back(temp_holder); cout > temp_h
Java 的开发过程中免不了与 Date 类型纠缠,准备总结一下项目经常使用的日期相关操作,JDK 版本 1.7,如果能够帮助大家节约那么几分钟起身活动一下,去泡杯咖啡,便是极好的,嘿嘿。当然,我
我正在使用 jquery ui 日期选择器来获取 fromDate 和 toDate 以下是from日期的代码 $("#from_date").datepicker({
我是一名优秀的程序员,十分优秀!