Go语言在Linux中的数据库操作指南
一 环境准备与驱动选择
sudo apt install mysql-server 或 CentOS/RHEL 使用 sudo yum install mysql-server 安装 MySQL;PostgreSQL 可用系统包管理器安装并启动服务。完成后用 mysql -u root -p 或 psql 验证。go get -u github.com/go-sql-driver/mysqlgithub.com/lib/pq(database/sql 接口)或高性能的 pgx v5:go get github.com/jackc/pgx/v5二 连接与初始化
database/sql 打开连接,注意 sql.Open 并不会立即建立物理连接,需 db.Ping() 验证;通过 DSN(数据源名称)配置连接参数。"user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"SetMaxOpenConns、SetMaxIdleConns、SetConnMaxLifetime"user=postgres dbname=test sslmode=disable"pgx.Connect(context.Background(), "postgres://user:pass@localhost/db")三 常见数据库快速上手
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/go_demo?charset=utf8mb4&parseTime=True&loc=Local"
db, err := sql.Open("mysql", dsn)
if err != nil { log.Fatal(err) }
defer db.Close()
if err = db.Ping(); err != nil { log.Fatal(err) }
fmt.Println("Connected to MySQL")
// 连接池
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
var id int
var name string
err = db.QueryRow("SELECT id, name FROM users WHERE id = ?", 1).Scan(&id, &name)
if err != nil {
if err == sql.ErrNoRows {
log.Println("No rows")
} else {
log.Fatal(err)
}
return
}
fmt.Printf("User: %d, %s\n", id, name)
}
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
dsn := "postgres://postgres:12345678@localhost/mydb?sslmode=disable"
db, err := sql.Open("postgres", dsn)
if err != nil { log.Fatal(err) }
defer db.Close()
if err = db.Ping(); err != nil { log.Fatal(err) }
fmt.Println("Connected to PostgreSQL")
var version string
err = db.QueryRow("SELECT version()").Scan(&version)
if err != nil { log.Fatal(err) }
fmt.Println("PG version:", version)
}
? 或 $1)防止 SQL 注入;QueryRow().Scan() 处理单行;rows.Next() 流式遍历结果集并在最后检查 rows.Err()。四 CRUD 与事务
db.Exec();通过 LastInsertId() 获取自增主键,通过 RowsAffected() 获取影响行数。QueryRow(),多行用 Query() 配合 rows.Scan();务必在循环后检查 rows.Err()。db.Begin() 获取事务对象 tx,在错误时 tx.Rollback(),成功时 tx.Commit();复杂场景可用保存点(Savepoint)实现细粒度回滚。tx, err := db.Begin()
if err != nil { log.Fatal(err) }
defer func() {
if p := recover(); p != nil { tx.Rollback(); panic(p) }
}()
_, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1)
if err != nil { tx.Rollback(); return }
_, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
if err != nil { tx.Rollback(); return }
if err = tx.Commit(); err != nil { log.Fatal(err) }
Prepare 提升性能与安全性;对批量写入使用事务减少提交开销。五 生产实践与排错要点
MaxOpenConns(如 CPU 核数的 2–3 倍)、MaxIdleConns(约为 MaxOpenConns 的 50%)、ConnMaxLifetime(如 30 分钟–2 小时);通过 db.Stats() 监控连接状态。parseTime=True&loc=Local 正确处理字符与时区;postgresql.conf 的 listen_addresses 与 pg_hba.conf 并重启服务。sql.ErrNoRows 与数据库特定错误(如 MySQL 错误码 1062 唯一键冲突);必要时实现指数退避重试。EXPLAIN 分析执行计划;分页优先 键集分页 提升大表性能。