postgresql - DefaultServeMux 中的 SQL 给出错误

标签 postgresql rest go

我正在尝试在 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/

相关文章:

postgresql - plpgsql 函数错误

sql - 如何在返回 View 行类型集的 pl/pgsql 函数中组合特定行?

node.js - 通过多模块方法访问 mongodb/mongoskin 的效率?

google-app-engine - App Engine 数据存储区 : How to set multiple values on a property using golang?

go - Go 中的缓冲 channel

amazon-web-services - 如何使用 Go 在 AWS S3 中设置 If-Modified-Since header

PostgreSQL 9.1 : Find exact expression in title

PostgreSQL 升级问题 $libdir/postgis-1.5 $libdir/plr

java - Jersey:将所有 POST 数据消耗到一个对象中

android - 对于文件> 1mb,驱动器REST API返回400