我的网络API应用中有一组功能。他们对Postgres数据库中的数据执行一些操作。
func CreateUser () {
db, err := sql.Open("postgres", "user=postgres password=password dbname=api_dev sslmode=disable")
// Do some db operations here
}
我认为函数应该与db相互独立地工作,所以现在我在每个函数中都有sql.Open(...)
。我不知道这是否是管理数据库连接的正确方法。
应用程序启动后我应该在某个地方打开它并将db作为参数传递给相应的函数而不是在每个函数中打开连接吗?
答案 0 :(得分:4)
每次需要时打开数据库连接都是浪费资源而且速度很慢。
相反,您应该在应用程序启动时(或首次请求时)创建一次sql.DB
,并将其传递到需要它的位置(例如,作为函数参数或通过某些上下文),或者只是制作它是一个全局变量,所以每个人都可以访问它。从多个goroutine打电话是安全的。
引自sql.Open()
的文件:
返回的数据库可以安全地由多个goroutine并发使用,并维护自己的空闲连接池。因此,Open函数应该只调用一次。很少需要关闭数据库。
您可以使用包init()
函数对其进行初始化:
var db *sql.DB
func init() {
var err error
db, err = sql.Open("yourdriver", "yourDs")
if err != nil {
log.Fatal("Invalid DB config:", err)
}
}
这里需要注意的一点是,sql.Open()
可能无法与您的数据库建立实际连接,它可能只是验证其参数。要测试您是否可以实际连接到数据库,请使用DB.Ping()
,例如:
func init() {
var err error
db, err = sql.Open("yourdriver", "yourDs")
if err != nil {
log.Fatal("Invalid DB config:", err)
}
if err = db.Ping(); err != nil {
log.Fatal("DB unreachable:", err)
}
}
答案 1 :(得分:0)
我将使用postgres示例
package main
导入必要的软件包,别忘了postgres驱动程序
import (
"database/sql"
_ "github.com/lib/pq" //postgres driver
)
在包范围内初始化您的连接
var db *sql.DB
具有用于连接的初始化功能
func init() {
var err error
db, err = sql.open("postgres", "connectionString")
//connectioString example => 'postgres://username:password@localhost/dbName?sslmode=disable'
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
// note, we haven't deffered db.Close() at the init function since the connection will close after init. you could close it at main or ommit it
}
主要功能
func main() {
defer db.Close() //optional
//run your db functions
}