简介
Go语言标准库 database/sql
,提供统一的数据库操作接口,支持连接池管理、事务控制、预处理语句等核心功能。开发者通过该库的通用接口(如sql.Open、db.Query,db.Exec)操作不同数据库,无需关心底层差异。
各数据库驱动实现
MySQL
:github.com/go-sql-driver/mysqlPostgreSQL
:github.com/lib/pqSQLite
:github.com/mattn/go-sqlite3SQL Server
:github.com/denisenkom/go-mssqldbOracle
: github.com/godror/godror
数据库连接和设置
- 默认启用连接池,避免频繁创建/销毁连接。
- 合理设置
MaxOpenConns
避免数据库过载,MaxIdleConns
减少连接重建开销。 - 监控指标:通过数据库的
SHOW PROCESSLIST
或驱动提供的统计接口观察连接使用情况。
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
// 连接数据库
db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname")
// 这个很少用。是关闭整个连接池。
defer db.Close()
连接池设置:
db.SetMaxOpenConns(100) // 最大活跃连接数
db.SetMaxIdleConns(10) // 最大空闲连接数
db.SetConnMaxLifetime(time.Hour) // 连接最大存活时间
Ping 机制:通过 db.Ping()
验证数据库连通性。
if err := db.Ping(); err != nil {
log.Fatal("数据库连接失败:", err)
}
查询数据
db.Query()
:执行 SELECT 查询,返回 *sql.Rows。db.QueryRow()
:执行单行查询,返回 *sql.Row。
注:必须关闭 Rows
和 Stmt
。忘记 rows.Close()
或 stmt.Close()
可能会导致连接池耗尽。
rows, _ := db.Query("SELECT id, name FROM users")
defer rows.Close() // 必须关闭释放资源
for rows.Next() {
var id int
var name string
rows.Scan(&id, &name) // 按列顺序扫描到变量
}
if err = rows.Err(); err != nil { // 检查遍历错误
// 处理错误
}
新增和更新数据
db.Exec()
:执行 INSERT/UPDATE/DELETE 等非查询操作。
事务
封装事务接口(BeginTx、Commit、Rollback),通过 db.Begin()
或 db.BeginTx()
开启事务。
隔离级别:通过 db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
设置。
tx, _ := db.Begin()
_, err1 := tx.Exec("UPDATE account SET balance = balance - 100 WHERE id = 1")
_, err2 := tx.Exec("UPDATE account SET balance = balance + 100 WHERE id = 2")
if err1 != nil || err2 != nil {
tx.Rollback() // 回滚
} else {
tx.Commit() // 提交
}
预处理语句
预处理语句,统一使用 ?
占位符。如下所示:
db.Query("SELECT * FROM users WHERE id = ? AND age > ?", 123, 18)
PostgreSQL 驱动(如 lib/pq 或 pgx)会自动将 ?
转换为 $1
, $2
, $3
...
使用预处理语句有如下优势:
- 防
SQL注入
:通过占位符(? 或 $1)绑定参数,自动转义输入。 - 性能提升:数据库预编译 SQL,重复执行时效率更高。
stmt, _ := db.Prepare("INSERT INTO users(name) VALUES(?)")
defer stmt.Close()
names := []string{"Alice", "Bob"}
for _, name := range names {
stmt.Exec(name)
}