Go语言的标准库 database/sql
提供了与 SQL 数据库交互的通用接口,但需要搭配具体的数据库驱动(如 MySQL、PostgreSQL 等)使用。以下是 database/sql
的核心方法及示例说明:
1. 连接数据库
sql.Open(driverName, dataSourceName)
连接数据库并返回 *sql.DB
对象(需先注册驱动)。
go
import (
"database/sql"
_ "github.com/go-sql-driver/mysql" // 匿名导入MySQL驱动
)
func main() {
// 数据源格式:用户名:密码@协议(地址:端口)/数据库名?参数
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/testdb")
if err != nil {
panic(err)
}
defer db.Close() // 确保关闭连接
}
2. 检查连接
DB.Ping()
验证数据库连接是否有效。
go
err = db.Ping()
if err != nil {
panic("数据库连接失败: " + err.Error())
}
3. 执行查询
DB.Query()
执行查询语句并返回多行结果(*sql.Rows
)。
go
rows, err := db.Query("SELECT id, name FROM users WHERE age > ?", 18)
if err != nil {
panic(err)
}
defer rows.Close() // 必须关闭Rows释放资源
for rows.Next() {
var id int
var name string
err = rows.Scan(&id, &name)
if err != nil {
panic(err)
}
fmt.Printf("ID: %d, Name: %s\n", id, name)
}
if err = rows.Err(); err != nil {
panic(err)
}
4. 执行单行查询
DB.QueryRow()
执行查询并返回单行结果(*sql.Row
)。
go
var name string
err = db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {
if err == sql.ErrNoRows {
fmt.Println("未找到记录")
} else {
panic(err)
}
}
fmt.Println("用户名:", name)
5. 执行非查询操作
DB.Exec()
执行插入、更新或删除操作,返回 sql.Result
。
go
result, err := db.Exec(
"INSERT INTO users (name, age) VALUES (?, ?)",
"Alice", 30,
)
if err != nil {
panic(err)
}
lastInsertID, _ := result.LastInsertId() // 获取自增ID
rowsAffected, _ := result.RowsAffected() // 获取影响行数
fmt.Printf("插入ID: %d, 影响行数: %d\n", lastInsertID, rowsAffected)
6. 预处理语句
DB.Prepare()
创建预处理语句(防止SQL注入,提升性能)。
go
stmt, err := db.Prepare("UPDATE users SET age = ? WHERE id = ?")
if err != nil {
panic(err)
}
defer stmt.Close()
_, err = stmt.Exec(31, 1) // 更新ID为1的用户的年龄
if err != nil {
panic(err)
}
7. 事务处理
DB.Begin()
开启事务,返回 *sql.Tx
对象。
go
tx, err := db.Begin()
if err != nil {
panic(err)
}
// 在事务中执行操作
_, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1)
if err != nil {
tx.Rollback() // 回滚事务
panic(err)
}
_, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
if err != nil {
tx.Rollback()
panic(err)
}
err = tx.Commit() // 提交事务
if err != nil {
panic(err)
}
8. 连接池配置
DB.SetMaxOpenConns(n)
和 DB.SetMaxIdleConns(n)
设置最大打开连接数和最大空闲连接数。
go
db.SetMaxOpenConns(25) // 最大并发连接数
db.SetMaxIdleConns(10) // 最大空闲连接数
db.SetConnMaxLifetime(time.Hour) // 连接最大存活时间
总结
- 核心方法 :
- 连接管理 :
sql.Open
,DB.Ping
,DB.Close
- 查询操作 :
DB.Query
,DB.QueryRow
,Rows.Scan
- 非查询操作 :
DB.Exec
,Result.LastInsertId
,Result.RowsAffected
- 预处理与事务 :
DB.Prepare
,DB.Begin
,Tx.Commit
,Tx.Rollback
- 连接池配置 :
SetMaxOpenConns
,SetMaxIdleConns
- 连接管理 :
- 注意事项 :
- 必须导入具体的数据库驱动(如
github.com/go-sql-driver/mysql
)。 - 始终检查错误并释放资源(如
rows.Close()
,stmt.Close()
)。 - 使用预处理语句防止 SQL 注入。
- 事务操作需确保提交或回滚,避免资源泄漏。
- 必须导入具体的数据库驱动(如