以下是代码:
package main
import (
"database/sql"
"errors"
"fmt"
_ "github.com/lib/pq"
)
type Post struct {
Id int
Content string
Author string
Comments []Comment
}
type Comment struct {
Id int
Content string
Author string
Post *Post
}
var Db *sql.DB
// connect to the Db
func init() {
var err error
//Db, err = sql.Open("postgres", "user=gwp dbname=gwp password=gwp sslmode=disable")
Db, err = sql.Open("postgres", "user=gwp dbname=gwp sslmode=disable")
if err != nil {
panic(err)
}
}
func (comment *Comment) Create() (err error) {
if comment.Post == nil {
err = errors.New("You need to specify the post that the comment belongs to.")
return
}
err = Db.QueryRow("insert into comments (content, author, post_id) values ($1, $2, $3) returning id", comment.Content, comment.Author, comment.Post.Id).Scan(&comment.Id)
return
}
// Get a single post
func GetPost(id int) (post Post, err error) {
post = Post{}
post.Comments = []Comment{}
err = Db.QueryRow("select id, content, author from posts where id = $1", id).Scan(&post.Id, &post.Content, &post.Author)
rows, err := Db.Query("select id, content, author from comments where post_id = $1", id)
if err != nil {
return
}
for rows.Next() {
comment := Comment{Post: &post}
err = rows.Scan(&comment.Id, &comment.Content, &comment.Author)
if err != nil {
return
}
post.Comments = append(post.Comments, comment)
}
rows.Close()
return
}
// Create a new post
func (post *Post) Create() (err error) {
err = Db.QueryRow("insert into posts (content, author) values ($1, $2) returning id", post.Content, post.Author).Scan(&post.Id)
return
}
func main() {
post := Post{Content: "Hello World!", Author: "Sau Sheong"}
post.Create()
// Add a comment
comment := Comment{Content: "Good post!", Author: "Joe", Post: &post}
comment.Create()
readPost, _ := GetPost(post.Id)
fmt.Println(readPost) // {1 Hello World! Sau Sheong [{1 Good post! Joe 0xc20802a1c0}]}
fmt.Println(readPost.Comments) // [{1 Good post! Joe 0xc20802a1c0}]
fmt.Println(readPost.Comments[0].Post) // &{1 Hello World! Sau Sheong [{1 Good post! Joe 0xc20802a1c0}]}
}
init
函数未在任何地方使用,但如果我将其注释掉,程序将崩溃并出现以下错误:
/usr/local/Cellar/go/1.7.4_2/libexec/bin/go run /Users/kaiyin/golang/src/github.com/sausheong/gwp/Chapter_6_Storing_Data/sql_store2/store.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x5fa9a]
goroutine 1 [running]:
panic(0x1d62c0, 0xc42000c0e0)
/usr/local/Cellar/go/1.7.4_2/libexec/src/runtime/panic.go:500 +0x1a1
database/sql.(*DB).conn(0x0, 0x1, 0x22, 0x1c, 0x0)
/usr/local/Cellar/go/1.7.4_2/libexec/src/database/sql/sql.go:781 +0x3a
database/sql.(*DB).query(0x0, 0x216def, 0x40, 0xc42004fd80, 0x2, 0x2, 0x1, 0x10, 0xc42000cba0, 0x0)
/usr/local/Cellar/go/1.7.4_2/libexec/src/database/sql/sql.go:1074 +0x3b
database/sql.(*DB).Query(0x0, 0x216def, 0x40, 0xc42004fd80, 0x2, 0x2, 0x1, 0xc42000cba0, 0xc42004fd28)
/usr/local/Cellar/go/1.7.4_2/libexec/src/database/sql/sql.go:1062 +0x90
database/sql.(*DB).QueryRow(0x0, 0x216def, 0x40, 0xc42004fd80, 0x2, 0x2, 0x11200b7b18)
/usr/local/Cellar/go/1.7.4_2/libexec/src/database/sql/sql.go:1143 +0x70
main.(*Post).Create(0xc420018380, 0xc420018380, 0xc42004fe20)
/Users/kaiyin/golang/src/github.com/sausheong/gwp/Chapter_6_Storing_Data/sql_store2/store.go:69 +0xfe
main.main()
/Users/kaiyin/golang/src/github.com/sausheong/gwp/Chapter_6_Storing_Data/sql_store2/store.go:75 +0xd7
exit status 2
Process finished with exit code 1
对调试不是很有帮助。
知道这里发生了什么吗?谢谢!
答案 0 :(得分:4)
程序启动时会自动调用所有init
个函数。它必须进行其他代码所依赖的初始化。请参阅https://golang.org/doc/effective_go.html#init。