当注释掉一个未使用的函数时,会出现Go运行时错误。

huangapple go评论87阅读模式
英文:

Go runtime error when an unused func is commented out

问题

这是代码:

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

// 连接到数据库
func init() {
	var err error
	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
}

// 获取单个帖子
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
}

// 创建新帖子
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()

	// 添加评论
	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

这个错误信息对于调试并不是很有帮助。

你知道这里发生了什么吗?谢谢!

英文:

Here is the code:

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}]}
}

The init function is not used anywhere, but if I comment it out, the program crashes with the following error:

/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

Not very helpful for debugging.

Any idea what's going on here? Thanks!

答案1

得分: 4

所有的init函数在程序启动时会自动调用。它必须执行一些其他代码依赖的初始化操作。请参考https://golang.org/doc/effective_go.html#init。

英文:

All init functions are called automatically when the program starts. It must be doing some initialization that other code depends on. See https://golang.org/doc/effective_go.html#init.

huangapple
  • 本文由 发表于 2017年1月28日 03:13:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/41901370.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定