运行 PostgreSQL 查询时出现无效的内存地址错误。

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

Invalid memory address error when running postgres queries

问题

当我运行我的Go代码并对本地的PostgreSQL数据库进行查询时,我一直遇到这个错误。

错误信息:

panic serving [::1]:56708: runtime error: invalid memory address or nil pointer dereference
goroutine 23 [running]:
net/http.func·011()
    /usr/local/go/src/pkg/net/http/server.go:1100 +0xb7
runtime.panic(0x2ef0a0, 0x4d8ee4)
    /usr/local/go/src/pkg/runtime/panic.c:248 +0x18d
database/sql.(*DB).conn(0x0, 0x277a1, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:625 +0x751
database/sql.(*DB).Ping(0x0, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:452 +0x39
main.firstHandler(0x58e9a8, 0xc208052320, 0xc2080284e0)
    /Users/Tommy/Documents/gocode/server/server.go:122 +0x35
net/http.HandlerFunc.ServeHTTP(0x3c6be8, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1235 +0x40
github.com/gorilla/mux.(*Router).ServeHTTP(0xc2080186e0, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /Users/Audrey/gocode/src/github.com/gorilla/mux/mux.go:98 +0x292
net/http.(*ServeMux).ServeHTTP(0xc208022660, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1511 +0x1a3
net/http.serverHandler.ServeHTTP(0xc208004660, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1673 +0x19f
net/http.(*conn).serve(0xc208050500)
    /usr/local/go/src/pkg/net/http/server.go:1174 +0xa7e
created by net/http.(*Server).Serve
    /usr/local/go/src/pkg/net/http/server.go:1721 +0x313

Go代码:

func firstHandler(w http.ResponseWriter, r *http.Request) {
    err := db.Ping()
    if err != nil {
        log.Fatal(err)
    }
    rows, err := db.Query("SELECT id, created_at, updated_at FROM script WHERE updated_at = $1", 3)
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    var created_at, updated_at, id int
    for rows.Next() {
        err := rows.Scan(&id, &created_at, &updated_at)
        if err != nil {
            log.Fatal(err)     
        }
       fmt.Fprintf("%s %s %s", id, created_at, updated_at)
    }
}

var r = mux.NewRouter()
var db *sql.DB

func main() {
    db, err := sql.Open("postgres", "user=Tommy host=localhost dbname=dbgo sslmode=verify-full")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    r.HandleFunc("/ping", firstHandler)

    http.Handle("/", r)

    http.ListenAndServe(":8080", nil)
}

帮帮我。我做错了什么?我还参考了这个链接:https://gophercasts.io/lessons/4-postgres-basics。

英文:

I keep getting this error when I run my Go code which makes queries to my local postgres database.

Error:

panic serving [::1]:56708: runtime error: invalid memory address or nil pointer dereference
goroutine 23 [running]:
net/http.func·011()
    /usr/local/go/src/pkg/net/http/server.go:1100 +0xb7
runtime.panic(0x2ef0a0, 0x4d8ee4)
    /usr/local/go/src/pkg/runtime/panic.c:248 +0x18d
database/sql.(*DB).conn(0x0, 0x277a1, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:625 +0x751
database/sql.(*DB).Ping(0x0, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:452 +0x39
main.firstHandler(0x58e9a8, 0xc208052320, 0xc2080284e0)
    /Users/Tommy/Documents/gocode/server/server.go:122 +0x35
net/http.HandlerFunc.ServeHTTP(0x3c6be8, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1235 +0x40
github.com/gorilla/mux.(*Router).ServeHTTP(0xc2080186e0, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /Users/Audrey/gocode/src/github.com/gorilla/mux/mux.go:98 +0x292
net/http.(*ServeMux).ServeHTTP(0xc208022660, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1511 +0x1a3
net/http.serverHandler.ServeHTTP(0xc208004660, 0x58e9a8, 0xc208052320, 0xc2080284e0)
    /usr/local/go/src/pkg/net/http/server.go:1673 +0x19f
net/http.(*conn).serve(0xc208050500)
    /usr/local/go/src/pkg/net/http/server.go:1174 +0xa7e
created by net/http.(*Server).Serve
    /usr/local/go/src/pkg/net/http/server.go:1721 +0x313

Go:

func firstHandler(w http.ResponseWriter, r *http.Request) {
    err := db.Ping()
    if err != nil {
	    log.Fatal(err)
    }
    rows, err := db.Query("SELECT id, created_at, updated_at FROM script WHERE updated_at = $1", 3)
    if err != nil {
	    log.Fatal(err)
    }
    defer rows.Close()

    var created_at, updated_at, id int
    for rows.Next() {
	    err := rows.Scan(&id, &created_at, &updated_at)
	    if err != nil {
		    log.Fatal(err)	 
	    }
	   fmt.Fprintf("%s %s %s", id, created_at, updated_at)
    }
}

var r = mux.NewRouter()
var db *sql.DB

func main() {
    db, err := sql.Open("postgres", "user=Tommy host=localhost dbname=dbgo sslmode=verify-full")
    if err != nil {
	    log.Fatal(err)
    }
    defer db.Close()

    r.HandleFunc("/ping", firstHandler)

    http.Handle("/", r)

    http.ListenAndServe(":8080", nil)
}

Help. What am I doing wrong? I referred to this also: https://gophercasts.io/lessons/4-postgres-basics.

答案1

得分: 15

实际上,你声明了连接变量:

var db *sql.DB

但是你使用以下代码打开连接:

db, err := sql.Open("postgres", "user=Tommy host=localhost dbname=dbgo sslmode=verify-full")

请注意 := 符号(它将变量声明与赋值结合在一起)。这实际上会将全局的 db 变量屏蔽为一个局部变量。连接被打开,但是赋值给了局部变量。因此,全局的 db 变量的值是 nil。

当调用 firstHandler 函数时,它的值仍然是 nil,这会触发 panic。

将 := 替换为 =(并在之前声明 err 对象)。

英文:

Actually, you declare the connection with:

var db *sql.DB

but you open the connection with:

db, err := sql.Open("postgres", "user=Tommy host=localhost dbname=dbgo sslmode=verify-full")

Note the := (it combines a variable declaration with an assignment). This will actually shadow the global db variable by a local one. The connection is opened but assigned to the local variable. So the value of the global db variable is nil.

When the firstHandler function is called, its value is still nil, which triggers the panic.

Replace the := by a = (and declare the err object before).

huangapple
  • 本文由 发表于 2014年9月30日 23:58:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/26125143.html
匿名

发表评论

匿名网友

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

确定