在Go中使用SQL驱动程序连接池

And*_*nov 8 sql go

使用Go语言存储数据库连接的最佳实践是什么?

例如,在Java中,您可以使用单例,一些像Spring这样的IoC容器.它的生命周期中的最佳实践是什么?申请结束后如何发布?

Mar*_*ark 11

在这里使用Singleton模式也没有错.

我会用这样的东西:

var db *sql.DB = nil

func GetDB() (*sql.DB, error) {
    if db == nil {
        conn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=require",
            DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
        log.Println("Creating a new connection: %v", conn)

        d, err := sql.Open("postgres", conn)
        if err != nil {
            return nil, err
        }
        db = d
    }

    return db, nil
}
Run Code Online (Sandbox Code Playgroud)

使用此导出功能,您可以从所有其他包接收连接.

根据评论更新答案(感谢@all获取信息)!:

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

关闭数据库很少见,因为数据库句柄是长期存在的并且在许多goroutine之间共享.²

我会说没有强制理由在数据库连接上调用close.我没有发现任何其他陈述.尽管如此,我还是会defer GetDB().close()main函数中使用 - 只是为了代码的完整性.

我想要注意的另一件事是连接应该通过db.Ping()否则可以建立连接来验证,但数据库可能不存在.

有了这些新信息,我就不会费心使用一些互斥锁来确保数据库的建立.我会创建一个新的DBInit()init()在主包的功能内运行它.