Go / Golang sql.DB在函数中重用

时间:2013-11-14 12:41:39

标签: go odbc freetds unixodbc

sql.Open()返回* sql.DB

类型的变量

我有一个函数调用其他所有需要进行数据库调用的函数

更正确/更有效:

  • 将* sql.DB指针发送到每个函数,或
  • 在每个函数中创建一个新的* sql.DB对象

含义

func DoLotsOfThings() {
    db, _ := sql.Open()
    defer db.Close()
    DoTask1(db)
    DoTask2(db)
}

func DoLotsOfThings() {
    DoTask1()
    DoTask2()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

我问的原因是因为我正在向每个函数发送指针而我的驱动程序似乎已经破坏了。我正在使用http://code.google.com/p/odbc,这让我相信每个函数都应该有自己的函数,并且我可以依赖于驱动程序的内部结构。

修改

RE驱动程序破损,它只发生在高流量环境下。它只发生在十分钟左右的时间之后。这让我相信存在某种内存泄漏会导致使用驱动程序停止工作。但是我为* sql.DB的每个实例推迟db.Close(),所以我不知道我还能做些什么来解决这个问题。

andybalholm说连接池是内部处理的,这似乎是准确的,因为它只会在我尝试执行某些操作后中断,而不是在我调用sql.Open()

如果我让Go应用程序运行,它将无法执行任何类型的SQL查询,但如果我尝试单独连接到MSSQL并运行查询来运行其他Go测试,则可以正常运行。

2 个答案:

答案 0 :(得分:19)

全局声明var db *sql.DB,然后在代码中重复使用它。这是一个例子(简化):

var db *sql.DB

func DoLotsOfThings() {
    DoTask1(db)
    DoTask2(db)
}

func main() {
  db, _ = sql.Open() # or whatever you use
  defer db.Close()
  DoLotsOfThings()
}

全局声明*sql.DB还有一些额外的好处,例如SetMaxIdleConns(规范连接池大小)或整个应用程序的preparing SQL语句。

答案 1 :(得分:7)

您不需要在整个地方打开数据库连接。 database / sql包在内部进行连接池,根据需要打开和关闭连接,同时提供可以同时使用的单个连接的错觉。

可能你需要到别处寻找你的司机破损的原因。关于这一点的更多细节将使人们更容易弄清楚发生了什么。