在a.go中声明的golang,db * sql.DB在b.go中不可用(golang, db *sql.DB declared in a.go not available in b.go)

编程入门 行业动态 更新时间:2024-10-20 00:47:42
在a.go中声明的golang,db * sql.DB在b.go中不可用(golang, db *sql.DB declared in a.go not available in b.go)

我有两个.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

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 }

I have two .go files: a.go and b.go

I'm declaring a global db *sql.DB for my mysql database connection.

My goal is to declare db once and use it in all my package files, in this case b.go.

Everything builds fine, but I get an error when hitting my API endpoint /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

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 }

最满意答案

编辑 :正如DaveC所指出的,问题是使用:=仅在本地范围内启动变量。 事先声明错误将导致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全局变量和短变量定义 )

/编辑

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

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

EDIT: As pointed out by DaveC, the problem is that using := initiates a variable in the local scope only. Declaring err beforehand will cause the sql.Open to save the connection in the global instead of creating a new local, as follows:

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

This edit influenced by DaveC, tomasz, and Ben Darnell (Ben Darnell's answer: Go global variable and short variable definition)

/EDIT

Personally, I prefer to avoid globals where possible. To do this, change GetUsers to take an argument *sql.DB. Then change your a.go to have a custom gin.HandlerFunc that is a database receiver. In the example I've created a tools struct that you could use to pass in many "global" things.

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

更多推荐

本文发布于:2023-08-04 14:05:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1415984.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:中不   声明   golang   sql   db

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!