我想在一些Go代碼中初始化一個程序包範圍的變量來連接數據庫,但我總是得到一個零指針異常,所以很明顯,這個賦值沒有發生正常。這將引發一個錯誤:Golang的init()函數中的程序包範圍變量賦值
package main
import (
"fmt"
"database/sql"
_ "github.com/lib/pq"
)
var connection *sql.DB
func init() {
connectionString := "host=172.17.0.3 dbname=postgres user=postgres password=postgres port=5432 sslmode=disable"
connection, err := sql.Open(
"postgres",
connectionString,
)
check(err)
err = connection.Ping()
check(err)
}
func main() {
TestConnect()
}
func TestConnect() {
var pid int
err := connection.QueryRow("SELECT pg_backend_pid()").Scan(&pid)
check(err)
fmt.Printf("pid: %v", pid)
}
func check(err error) {
if err != nil {
panic(err)
}
}
這裏的錯誤:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4c1a1a]
goroutine 1 [running]:
database/sql.(*DB).conn(0x0, 0x70b7c0, 0xc4200102b8, 0x1, 0xc420055e08, 0x4c28df, 0xc4200b0000)
/usr/local/go/src/database/sql/sql.go:896 +0x3a
database/sql.(*DB).query(0x0, 0x70b7c0, 0xc4200102b8, 0x630335, 0x17, 0x0, 0x0, 0x0, 0x101, 0x741c80, ...)
/usr/local/go/src/database/sql/sql.go:1245 +0x5b
database/sql.(*DB).QueryContext(0x0, 0x70b7c0, 0xc4200102b8, 0x630335, 0x17, 0x0, 0x0, 0x0, 0x0, 0x8, ...)
/usr/local/go/src/database/sql/sql.go:1227 +0xb8
database/sql.(*DB).QueryRowContext(0x0, 0x70b7c0, 0xc4200102b8, 0x630335, 0x17, 0x0, 0x0, 0x0, 0xc420010cb0)
/usr/local/go/src/database/sql/sql.go:1317 +0x90
database/sql.(*DB).QueryRow(0x0, 0x630335, 0x17, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/database/sql/sql.go:1325 +0x7c
main.TestConnect()
/home/tom/go/src/go-rest/ignore/connect.go:32 +0x82
main.main()
/home/tom/go/src/go-rest/ignore/connect.go:26 +0x20
exit status 2
不過,如果我打開它,這樣我就可以使用=
操作上connection
而不是:=
...
package main
import (
"fmt"
"database/sql"
_ "github.com/lib/pq"
)
var connection *sql.DB
func init() {
connectionString, err := GetConnectionString()
connection, err = sql.Open(
"postgres",
connectionString,
)
check(err)
err = connection.Ping()
check(err)
}
func main() {
TestConnect()
}
func TestConnect() {
var pid int
err := connection.QueryRow("SELECT pg_backend_pid()").Scan(&pid)
check(err)
fmt.Printf("pid: %v", pid)
}
func GetConnectionString() (string, error) {
return "host=172.17.0.3 dbname=postgres user=postgres password=postgres port=5432 sslmode=disable", nil
}
func check(err error) {
if err != nil {
panic(err)
}
}
然後一切按預期工作,變量被正確分配。由於err
變量先前未定義,因此我必須使用:=
進行賦值,但這似乎假定我正在初始化變量的函數作用域connection
變量,而不是嘗試將其分配給包變量connection
變量。 Go有沒有辦法強制這個任務?就目前而言,我需要編寫無用的樣板代碼以使其以正確的方式工作,似乎應該有更好的方法。
當然,這種可能性也表明我正在嘗試做一些我可能不應該做的事情。根據我的研究,儘管this guide似乎暗示使用包級數據庫連接比根據需要創建/關閉連接更好。
感謝您的回覆,這確實有幫助。我誤解了':='操作符是要聲明「新」變量,而不是處理範圍界定。 Go對我來說還很新,所以非常感謝您花時間回覆。 – carusot42
@ carusot42不客氣。快樂學習。 – jeevatkm