为了账号安全,请及时绑定邮箱和手机立即绑定

GoLang:在数据库中丢失范围

GoLang:在数据库中丢失范围

Go
30秒到达战场 2021-10-04 15:59:40
Go 新手,来自 .Net-land,所以请耐心等待......希望能得到一些关于构建我的 Go 应用程序的指导,特别是在管理和重用数据库连接方面。我已将我的 db 代码拆分为一个包,以允许将 db-lookups 放入像存储库层一样处理 sql 查找的包中。我希望能够灵活地将我的 db 层与我的应用程序服务分离,以便在必要时轻松替换我的数据库。基本上,我正在寻找有关如何以及何时处理 sql connect 并在应用程序中保存 sql.DB 指针的一些指导。我需要在 main.go 中保留一个全局指针还是可以在我的 mysql 包中管理连接?这是我的代码:package mysqlstorageimport (    "database/sql"    "fmt"    "log"    "types")var db *sql.DBfunc Connect() {    db, dberr := sql.Open(“<CONNECTION_STRING>“)    if dberr != nil {        fmt.Println(dberr)    }}func SaveUser(u types.User) {    // use db here!     ....}func GetUser(id string) types.User {    // use db here!    ....}在运行我的 main.go 并使用我的 userservices 包尝试保存用户时,我遇到了一个问题,我似乎失去了我的指针范围:-2015/05/03 17:49:08 http: panic serving [::1]:50106: runtime error: invalid memory address or nil pointer dereference goroutine 7 [running]: net/http.func·011() /usr/local/Cellar/go/1.4.2/libexec/src/net/http/server.go:1130 +0xbb database/sql.(*DB).conn(0x0, 0x10, 0x0, 0x0)   /usr/local/Cellar/go/1.4.2/libexec/src/database/sql/sql.go:634 +0x7ae database/sql.(*DB).Ping(0x0, 0x0, 0x0)    /usr/local/Cellar/go/1.4.2/libexec/src/database/sql/sql.go:462 +0x3a mysqlstorage.SaveUser(0x0, 0xc20805425a, 0x7, 0xc208054280, 0x11, 0xc208054268, 0x6, 0xc208054274, 0x5)    /Users/<USERNAME>/Desktop/go/<APPNAME>/api/src/mysqlstorage/mysqlstorage.go:24    +0x35 services.CreateUser(0x57c148, 0xc2080563c0, 0xc2080329c0)     /Users/<USERNAME>/Desktop/go/<APPNAME>/api/src/services/userservices.go:30    +0x398 net/http.HandlerFunc.ServeHTTP(0x3d02a0, 0x57c148, 0xc2080563c0, 0xc2080329c0)   任何指导将不胜感激!谢谢你们!
查看完整描述

2 回答

?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

我认为您的问题是由于您使用了操作员db,Connect()范围被遮蔽了:=。如果你改变你的方法来声明一个dberrvar:


func Connect() {

    var dberr error

    db, dberr = sql.Open(“<CONNECTION_STRING>“)


    if dberr != nil {

        fmt.Println(dberr)

    }

}

您的代码将按预期工作


查看完整回答
反对 回复 2021-10-04
?
PIPIONE

TA贡献1829条经验 获得超9个赞

您超出范围是因为您正在通过db, err :=赋值创建一个局部变量 db ,然后在 Connect func 返回时超出范围。

一般就使用sql.DB

从database/sql 包:

DB 是表示零个或多个底层连接池的数据库句柄。多个 goroutine 并发使用是安全的。

sql 包自动创建和释放连接;它还维护一个空闲连接的空闲池。

返回的数据库对于多个 goroutine 并发使用是安全的,并维护自己的空闲连接池。因此,应该只调用一次 Open 函数。很少需要关闭数据库。

也就是说,您想打开连接一次,然后在整个过程中保持打开状态。这样,当您完成(或遇到致命或恐慌)时实际关闭它的唯一可靠方法是defer db.Close()在打开它后立即执行惯用的 go ,这需要在主函数中完成。

您仍然可以将 Connect 函数保留在您的包中,并使用它来初始化全局包变量 db,但从 main 调用一次并将 *sql.DB 返回到 main,以便您可以延迟 db.Close()。


查看完整回答
反对 回复 2021-10-04
  • 2 回答
  • 0 关注
  • 236 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信