我正在尝试在 Go 中做一个 REST API。查询在放置在主处理程序中时有效(显示在终端中),但在移动到所需的处理程序时会在浏览器中出错。
localhost:8080/<------ 浏览器报错(不显示任何内容)并且终端显示多条错误消息 - 其中之一是:
http: panic serving [::1]:51100: runtime error: invalid memory address or nil pointer dereference
localhost:8080/getuser <---给出正确的响应
Getuser
package main
import (
"fmt"
"log"
"net/http"
"database/sql"
_ "github.com/lib/pq"
)
const (
host = "127.0.0.1"
port = 5432
user = "test"
password = "pw"
dbname = "Test"
)
var db *sql.DB
type User struct {
USER_ID string
USER_NAME string
}
func handleRequests() {
http.HandleFunc("/", index)
http.HandleFunc("/getuser", Getuser)
}
func index(w http.ResponseWriter, r *http.Request){
rows, err := db.Query(`SELECT "USER_ID","USER_NAME" FROM users`)
if err != nil {
http.Error(w, http.StatusText(500), 500)
return
}
defer rows.Close()
for rows.Next() {
user := User{}
err := rows.Scan(&user.USER_ID, &user.USER_NAME)
if err != nil {
http.Error(w, http.StatusText(500), 500)
}
fmt.Fprintf(w, "%s, %s\n", user.USER_ID, user.USER_NAME)
}
}
func Getuser(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Getuser") // <-------------------------this works!
}
func main() {
handleRequests()
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=require",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatalln(err)
}
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
log.Fatal(http.ListenAndServe(":8080", nil))
}
编辑
终端中完整的错误列表
created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b 2018/03/23 08:36:39 http: panic serving [::1]:51390: runtime error: invalid memory address or nil pointer dereference goroutine 36 [running]: net/http.(*conn).serve.func1(0xc4201d80a0) /usr/local/go/src/net/http/server.go:1726 +0xd0 panic(0x1294460, 0x1471840) /usr/local/go/src/runtime/panic.go:505 +0x229 database/sql.(*DB).conn(0x0, 0x13277e0, 0xc42009e020, 0xc420028f01, 0xc4200a0218, 0xc4200a0220, 0xc4201e8b01) /usr/local/go/src/database/sql/sql.go:1015 +0x3a database/sql.(*DB).query(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x12ec601, 0x8, ...) /usr/local/go/src/database/sql/sql.go:1437 +0x66
database/sql.(*DB).QueryContext(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x10825ed, 0xc4201d0180, ...) /usr/local/go/src/database/sql/sql.go:1419 +0xd2 database/sql.(*DB).Query(0x0, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0xc4201ec070, 0x8000000000000000, 0x0) /usr/local/go/src/database/sql/sql.go:1433 +0x82 main.Getsign(0x13275a0, 0xc4202020e0, 0xc4201f4100) /Users/sibert/go/src/main/api.go:55 +0x65 net/http.HandlerFunc.ServeHTTP(0x1302020, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:1947 +0x44 net/http.(*ServeMux).ServeHTTP(0x147cc00, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:2337 +0x130 net/http.serverHandler.ServeHTTP(0xc42009b2b0, 0x13275a0, 0xc4202020e0, 0xc4201f4100) /usr/local/go/src/net/http/server.go:2694 +0xbc net/http.(*conn).serve(0xc4201d80a0, 0x13277a0, 0xc4201b4280) /usr/local/go/src/net/http/server.go:1830 +0x651 created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b 2018/03/23 08:36:39 http: panic serving [::1]:51391: runtime error: invalid memory address or nil pointer dereference goroutine 24 [running]: net/http.(*conn).serve.func1(0xc4200b4b40) /usr/local/go/src/net/http/server.go:1726 +0xd0 panic(0x1294460, 0x1471840) /usr/local/go/src/runtime/panic.go:505 +0x229 database/sql.(*DB).conn(0x0, 0x13277e0, 0xc42009e020, 0xc420024501, 0xc4200a0318, 0xc4200a0320, 0xc420052b01) /usr/local/go/src/database/sql/sql.go:1015 +0x3a database/sql.(*DB).query(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x12ec601, 0x8, ...) /usr/local/go/src/database/sql/sql.go:1437 +0x66 database/sql.(*DB).QueryContext(0x0, 0x13277e0, 0xc42009e020, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0x10825ed, 0xc420140480, ...) /usr/local/go/src/database/sql/sql.go:1419 +0xd2 database/sql.(*DB).Query(0x0, 0x12f7553, 0x26, 0x0, 0x0, 0x0, 0xc42009eb10, 0x8000000000000000, 0x0) /usr/local/go/src/database/sql/sql.go:1433 +0x82 main.Getsign(0x13275a0, 0xc42019e0e0, 0xc42019a300) /Users/sibert/go/src/main/api.go:55 +0x65 net/http.HandlerFunc.ServeHTTP(0x1302020, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:1947 +0x44 net/http.(*ServeMux).ServeHTTP(0x147cc00, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:2337 +0x130 net/http.serverHandler.ServeHTTP(0xc42009b2b0, 0x13275a0, 0xc42019e0e0, 0xc42019a300) /usr/local/go/src/net/http/server.go:2694 +0xbc net/http.(*conn).serve(0xc4200b4b40, 0x13277a0, 0xc4200a0780) /usr/local/go/src/net/http/server.go:1830 +0x651 created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:2795 +0x27b
最佳答案
您遇到的是变量阴影的经典案例。
:=
创建了一个新的 db
变量,它隐藏了你的包级 db
变量。 db
的设置值只存在于你的 main 函数的范围内,而你的包级 db
变量仍然是一个 nil 指针,因此当你尝试执行方法调用时nil
,在您的索引处理程序中,您会感到 panic 。
您的 Getuser 处理程序工作的原因与 DefaultServeMux 无关,这只是因为您没有尝试访问 nil 值的成员函数。
解决这个问题的方法是在你的 main 函数中预先声明 err
变量并将 :=
更改为简单赋值 =
func main() {
// ...
var err error
// this will now correctly set your package level variable
db, err = sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatalln(err)
}
// ...
}
关于postgresql - DefaultServeMux 中的 SQL 给出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49444220/