面试题答案
一键面试- 设计方案:
- 使用
sync.Pool
来管理数据库连接资源。sync.Pool
是Go语言提供的一个对象池,它能在高并发场景下高效地复用对象,减少内存分配和垃圾回收压力。 - 利用闭包来封装获取和释放连接的逻辑,确保连接的正确使用和并发安全。
- 在获取连接时,从
sync.Pool
中获取,如果池为空则创建新连接。 - 在释放连接时,将连接放回
sync.Pool
中,而不是直接销毁。
- 使用
- 关键代码片段:
package main
import (
"database/sql"
"fmt"
"sync"
_ "github.com/go - sql - driver/mysql" // 假设使用MySQL,根据实际情况调整
)
var (
dbPool *sql.DB
connectionPool sync.Pool
)
func init() {
var err error
dbPool, err = sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/database_name")
if err != nil {
panic(err.Error())
}
// 初始化连接池
connectionPool = sync.Pool{
New: func() interface{} {
conn, err := dbPool.Conn(nil)
if err != nil {
panic(err.Error())
}
return conn
},
}
}
// 获取连接的闭包
func getConnection() func() (*sql.Conn, error) {
return func() (*sql.Conn, error) {
conn := connectionPool.Get().(*sql.Conn)
// 检查连接是否可用,如果不可用则重新获取
err := conn.Ping()
if err != nil {
conn.Close()
conn = connectionPool.Get().(*sql.Conn)
}
return conn, nil
}
}
// 释放连接的闭包
func releaseConnection() func(conn *sql.Conn) {
return func(conn *sql.Conn) {
connectionPool.Put(conn)
}
}
在实际使用中,可以这样调用:
func main() {
getConn := getConnection()
releaseConn := releaseConnection()
conn, err := getConn()
if err != nil {
fmt.Println("获取连接失败:", err)
return
}
defer releaseConn(conn)
// 执行数据库操作
rows, err := conn.Query("SELECT * FROM some_table")
if err != nil {
fmt.Println("查询失败:", err)
return
}
defer rows.Close()
// 处理查询结果
for rows.Next() {
// 处理逻辑
}
}