英文:
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.
> 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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论