DefaultServeMux中的SQL提供错误

时间:2018-03-23 07:09:42

标签: postgresql rest go

我正在尝试在Go中执行REST API。查询在放置在主处理程序中时显示(在终端中显示),但在移动到所需处理程序时在浏览器中出错。

localhost:8080 /< ------浏览器发出错误(未显示任何内容),终端显示多条错误消息 - 其中一条是:

  

http:panic serving [:: 1]:51100:运行时错误:无效的内存地址或nil指针取消引用

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

修改

终端

中的完整错误列表
  

由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:运行时错误:无效   内存地址或无指针取消引用goroutine 36 [运行]:   净/ HTTP(*康恩).serve.func1(0xc4201d80a0)           /usr/local/go/src/net/http/server.go:1726 + 0xd0恐慌(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由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:运行时错误:无效   内存地址或零指针取消引用goroutine 24 [运行]:   净/ HTTP(*康恩).serve.func1(0xc4200b4b40)           /usr/local/go/src/net/http/server.go:1726 + 0xd0恐慌(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由net / http。(* Server)创建.Serve           /usr/local/go/src/net/http/server.go:2795 + 0x27b

1 个答案:

答案 0 :(得分:1)

您遇到的是变量阴影的经典案例。

:=会创建一个新的db变量,该变量会影响您的包级别db变量。 db的设置值仅存在于main函数的范围内,而包级别db变量仍作为nil指针,因此当您尝试在nil上执行方法调用时,在你的索引处理程序中,你会感到恐慌。

Getuser处理程序工作的原因与DefaultServeMux无关,原因很简单,因为您没有尝试访问nil值的成员函数。

解决此问题的方法是在预先处理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)
    }
// ...
}