要复用连接应该用连接池,初始化连接池可以用单例。
go 的 mysql 基本都有实现连接池。
mysql 库
<br>// Prefer a free connection, if possible.<br> numFree := len(db.freeConn)<br> if strategy == cachedOrNewConn && numFree > 0 {<br> conn := db.freeConn[0]<br> copy(db.freeConn, db.freeConn[1:])<br> db.freeConn = db.freeConn[:numFree-1]<br> conn.inUse = true<br> db.mu.Unlock()<br> if conn.expired(lifetime) {<br> conn.Close()<br> return nil, driver.ErrBadConn<br> }<br> // Lock around reading lastErr to ensure the session resetter finished.<br> conn.Lock()<br> err := conn.lastErr<br> conn.Unlock()<br> if err == driver.ErrBadConn {<br> conn.Close()<br> return nil, driver.ErrBadConn<br> }<br> return conn, nil<br> }<br>
sql 库默认有连接池
sql 库默认是有连接池,这个是正确的,但你如何在不同的 package 共用同一个连接?
把 connection 指针传到各个 package 里?
这种方法也是麻烦
在Golang中实现MySQL单例模式,可以确保整个应用程序生命周期中只创建一个MySQL连接实例,从而避免频繁创建和销毁连接带来的性能开销。以下是实现MySQL单例的一个简单示例:
- 定义一个结构体来保存MySQL连接:
type MySQLClient struct {
db *sql.DB
}
var instance *MySQLClient
var once sync.Once
这里使用sync.Once
来保证MySQLClient实例只被初始化一次。
- 实现单例的获取方法:
func GetMySQLClient() *MySQLClient {
once.Do(func() {
dsn := "username:password@tcp(127.0.0.1:3306)/dbname"
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
if err := db.Ping(); err != nil {
log.Fatal(err)
}
instance = &MySQLClient{db: db}
})
return instance
}
GetMySQLClient
方法使用sync.Once
的Do
方法确保连接只被创建一次。如果连接成功,它将instance
设置为新创建的MySQLClient实例。
- 使用单例:
func main() {
client := GetMySQLClient()
// 使用client.db进行数据库操作
}
通过这种方式,你可以在整个应用程序中安全地重用同一个MySQL连接实例,无需担心并发问题或资源泄露。这种模式对于需要频繁访问数据库的应用程序特别有用。