在a.go中声明的golang,db * sql.DB在b.go中不可用

时间:2015-05-19 02:54:29

标签: sql database go go-gin

我有两个.go文件:a.go和b.go

我正在为我的mysql数据库连接声明一个全局db * sql.DB。

我的目标是声明db一次并在我的所有包文件中使用它,在本例中为b.go。

一切都很好,但是在我的API端点/用户

时遇到错误
22:48:52 app         | 2015/05/18 22:48:52 http: panic serving 127.0.0.1:55742: runtime error: invalid memory address or nil pointer dereference
goroutine 6 [running]:
net/http.func·011()
    /usr/local/go/src/net/http/server.go:1130 +0xbb
database/sql.(*DB).conn(0x0, 0x4da104, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:634 +0x7ae
database/sql.(*DB).query(0x0, 0x809e70, 0x16, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:933 +0x43
database/sql.(*DB).Query(0x0, 0x809e70, 0x16, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:924 +0xa6
main.GetUsers(0x0, 0x0, 0x0)
    /var/www/zazok.com/api/src/app/user.go:15 +0xc0
main.func·001(0xc2080424d0)
    /var/www/zazok.com/api/src/app/app.go:35 +0x1f
github.com/gin-gonic/gin.(*Context).Next(0xc2080424d0)
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/context.go:114 +0x95
github.com/gin-gonic/gin.func·006(0xc2080424d0)
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/logger.go:49 +0x68
github.com/gin-gonic/gin.(*Context).Next(0xc2080424d0)
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/context.go:114 +0x95
github.com/gin-gonic/gin.func·009(0x7f1123351408, 0xc208036280, 0xc2080328f0, 0x0, 0x0, 0x0)
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/routergroup.go:57 +0xa3
github.com/julienschmidt/httprouter.(*Router).ServeHTTP(0xc20803af60, 0x7f1123351408, 0xc208036280, 0xc2080328f0)
    /var/www/zazok.com/api/src/github.com/julienschmidt/httprouter/router.go:299 +0x18e
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc208042000, 0x7f1123351408, 0xc208036280, 0xc2080328f0)
    /var/www/zazok.com/api/src/github.com/gin-gonic/gin/gin.go:156 +0x4d
net/http.serverHandler.ServeHTTP(0xc208030120, 0x7f1123351408, 0xc208036280, 0xc2080328f0)
    /usr/local/go/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc2080361e0)
    /usr/local/go/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:1751 +0x35e

a.go

package main

import (
    "database/sql"
    "github.com/gin-gonic/gin"
    _ "github.com/go-sql-driver/mysql"
)

var (
    prefix string = "/api/v1" // API prefix
    db     *sql.DB
)

// Boots up this whole thing
func main() {
    // Setting up DB
    db, err := sql.Open("mysql", "root:password@unix(/var/run/mysqld/mysqld.sock)/test.com?collation=utf8_general_ci")
    if err != nil {
        panic(err)
    }

    defer db.Close()

    err = db.Ping()
    if err != nil {
        panic(err)
    }

    r := gin.New()

    r.Use(gin.Logger())

    r.GET(prefix+"/users", func(c *gin.Context) {

        t := GetUsers()

        c.JSON(200, t)
    })

    r.Run(":3000")
}

b.go

package main

import (
    "log"
)

type User struct {
    Id          int    `json:"id"`
    Name        string `json:"name"`
}

func GetUsers() []User {
    a := []User{}

    _, err := db.Query("SELECT name FROM users")
    if err != nil {
        log.Fatal(err)
    }

    return a
}

2 个答案:

答案 0 :(得分:3)

我认为这是一个经典的Go bug,它与使用多个文件无关。

本声明:

db, err := sql.Open("mysql", ...)

在主范围内声明新变量db(注意:=),并且您的全局变量未被触及(nil)。

您可以轻松修复它:

var err error
db, err = sql.Open("mysql", ...)

答案 1 :(得分:2)

修改: 正如DaveC所指出的,问题是使用for (int i = 0; i <= puzzleListY.size(); i++) { // remove = 仅在本地范围内启动变量。事先声明错误将导致sql.Open在全局中保存连接而不是创建新的本地,如下所示:

:=

此编辑受到DaveC,tomasz和Ben Darnell的影响(Ben Darnell的答案:Go global variable and short variable definition

<强> /修改

就个人而言,我更愿意尽可能避免使用全局变量。为此,请更改GetUsers以获取参数* sql.DB。然后将a.go更改为具有数据库接收器的自定义func main() { var err error // <- Declare err // Use = instead of := db, err = sql.Open("mysql", "root:password@unix(/var/run/mysqld/mysqld.sock)/test.com?collation=utf8_general_ci") ... 。在示例中,我创建了一个工具结构,您可以使用它来传递许多&#34; global&#34;的东西。

gin.HandlerFunc