How frequently should I be calling sql.Open in my program?

huangapple go评论143阅读模式
英文:

How frequently should I be calling sql.Open in my program?

问题

正如标题所说,我不知道是否拥有多个sql.Open语句是好事还是坏事,或者我是否应该有一个只包含初始化的文件,类似于:

var db *sql.DB

func init() {
    var err error
    db, err = sql.Open
}

只是想知道最佳实践是什么。谢谢!

英文:

As the title says I don't know if having multiple sql.Open statements is a good or bad thing or what or if I should have a file with just an init that is something like:

var db *sql.DB


func init() {
    var err error
    db, err = sql.Open
}

just wondering what the best practice would be. Thanks!

答案1

得分: 7

你至少应该检查一下错误。如在“连接到数据库”中所述:

请注意,Open函数并不直接打开数据库连接:这个操作会被推迟到执行查询操作时才会发生。如果想在执行查询之前验证是否可以建立连接,请使用Ping函数:

if err := db.Ping(); err != nil {
  log.Fatal(err)
}

在使用完毕后,可以使用Close函数关闭数据库连接。

如果可能的话,将打开的数据库连接数限制在最小值。参见“Go/Golang函数中的sql.DB重用”:

你不应该在各个地方都打开数据库连接。database/sql包在内部进行连接池管理,根据需要打开和关闭连接,同时提供了一个看似可以并发使用的单一连接。

正如elithrar评论中指出的那样,database/sql/#Open确实提到:

返回的DB对象可以安全地被多个goroutine并发使用,并且它维护着自己的空闲连接池。因此,应该只调用一次Open函数。很少需要手动关闭DB对象。

正如这里所提到的:

在全局范围内声明*sql.DB也有一些额外的好处,比如SetMaxIdleConns(调整连接池大小)或者在整个应用程序中预编译SQL语句。

你可以使用一个名为init函数,即使没有main()函数也会运行:

var db *sql.DB
func init() {
    db, err = sql.Open(DBparms....)
}

init()函数总是会被调用,无论是否有main函数,所以如果你导入了一个包,它有一个init函数,那么它将被执行。一个包可以有多个init函数,它们将按照它们在代码中出现的顺序执行(当然,在所有变量初始化之后)。

英文:

You should at least check the error.
As mentioned in "Connecting to a database":

> Note that Open does not directly open a database connection: this is deferred until a query is made. To verify that a connection can be made before making a query, use the Ping function:

if err := db.Ping(); err != nil {
  log.Fatal(err)
}

> After use, the database is closed using Close.

If possible, limit the number of opened connection to a database to a minimum.
See "Go/Golang sql.DB reuse in functions":

> You shouldn't need to open database connections all over the place.
The database/sql package does connection pooling internally, opening and closing connections as needed, while providing the illusion of a single connection that can be used concurrently.

As elithrar points out in the comment, database.sql/#Open does mention:

> The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections.
Thus, the Open function should be called just once.
It is rarely necessary to close a DB.

As mentioned here

> Declaring *sql.DB globally also have some additional benefits such as SetMaxIdleConns (regulating connection pool size) or preparing SQL statements across your application.

You can use a function init, which will run even if you don't have a main():

var db *sql.DB
func init() {
    db, err = sql.Open(DBparms....)
}

> init() is always called, regardless if there's main or not, so if you import a package that has an init function, it will be executed.
You can have multiple init() functions per package, they will be executed in the order they show up in the code (after all variables are initialized of course).

huangapple
  • 本文由 发表于 2015年11月7日 11:38:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/33578876.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定