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

时间:2015-11-30 09:51:25

标签: sql go

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

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

1 个答案:

答案 0 :(得分:8)

在这里使用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
}

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

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

  

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

     

关闭数据库很少见,因为数据库句柄是长寿命的   许多goroutines之间共享。²

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

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

使用这些新信息,我不会使用某些互斥锁来确保数据库已建立。我将创建一个新的DBInit()并在主包的init()函数内运行它。