gpt4 book ai didi

sql - db *sql.DB 在 a.go 中声明在 b.go 中不可用

转载 作者:IT王子 更新时间:2023-10-29 02:27:54 25 4
gpt4 key购买 nike

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

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

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

一切正常,但在访问我的 API 端点/users 时出现错误

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

去吧

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

去吧

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
}

最佳答案

编辑:正如 DaveC 所指出的,问题在于使用 := 仅在本地范围内启动变量。预先声明 err 将导致 sql.Open 将连接保存在全局而不是创建一个新的本地,如下所示:

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")
...

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

/编辑

就个人而言,我更愿意尽可能避免使用全局变量。为此,将 GetUsers 更改为带参数 *sql.DB。然后将您的 a.go 更改为具有作为数据库接收器的自定义 gin.HandlerFunc。在示例中,我创建了一个 tools 结构,您可以使用它来传递许多“全局”事物。

package main

import (
"database/sql"

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

var (
prefix = "/api/v1" // API prefix
)

type tools struct {
db *sql.DB
}

func (t tools) dispatch() gin.HandlerFunc {
return func(c *gin.Context) {
GetUsers(t.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("DB connection failed")
}
defer db.Close()

t := tools{db}

r := gin.New()

r.Use(gin.Logger())

r.GET(prefix+"/users", t.dispatch())

r.Run(":3000")
}

关于sql - db *sql.DB 在 a.go 中声明在 b.go 中不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30315951/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com