Go 的 database/sql 是抽象接口层,需显式导入驱动;sql.Open 不建连,须调用 db.Ping() 验证;密码含特殊字符需 url.QueryEscape;QueryRow 延迟报 sql.ErrNoRows,Query 需手动检查 rows.Err() 并调用 rows.Close();字段名须与列名完全一致且区分大小写;预处理语句需按场景使用;连接池参数 SetMaxOpenConns 等必须合理配置。

Go 的 database/sql 不是数据库驱动,而是抽象接口层 —— 你必须显式导入并注册驱动(如 github.com/lib/pq 或 github.com/go-sql-driver/mysql),否则 sql.Open 会返回 "sql: unknown driver" 错误。
初始化连接时必须调用 db.Ping() 验证连通性
sql.Open 只校验参数、不建立真实连接;真正报错常发生在首次查询时。生产环境务必在初始化后立即执行 db.Ping(),避免服务启动后首请求失败。
- 使用
context.WithTimeout控制探测时间,防止卡死:ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() if err := db.PingContext(ctx); err != nil { log.Fatal("DB ping failed:", err) } - 连接字符串中的密码若含特殊字符(如
@、/),需用url.QueryEscape编码,否则解析失败 - MySQL 驱动默认不启用自动重连,连接中断后需自行处理重试逻辑或使用连接池配置
QueryRow 和 Query 的行为差异直接影响错误处理方式
QueryRow 适用于单行结果(如 SELECT ... LIMIT 1),它把 NoRows 错误延迟到 Scan 阶段才暴露;而 Query 返回 *Rows,需手动检查 rows.Err() 并调用 rows.Close()。
用大白话操作当前项目的 Git/GitHub——配置 GitHub(装 gh CLI + 登录 + 建仓库)、备份、拉取下载、查询历史、回滚代码、管理分支。当用户用日常语言表达 git 意图时触发(例如"git备份一下""git下载项目""git拉下来""git看看我改了啥""git回退到上一个版本""git新建个分支搞新功能""git合并到主分支""git
-
QueryRow(...).Scan(&v)失败时,err可能是sql.ErrNoRows,也可能是类型不匹配或网络错误 —— 别直接忽略sql.ErrNoRows - 用
Query循环读取时,必须在for rows.Next()后调用rows.Close(),否则连接不会归还给池,最终耗尽连接数 - 扫描结构体字段时,字段名必须与 SQL 列名(或别名)**完全一致且区分大小写**,否则值为零值且无提示
预处理语句(Prepare)不是性能银弹,要分场景使用
对于高频执行的相同 SQL(尤其带参数的 DML),Stmt 能复用执行计划、减少 SQL 解析开销;但对一次性查询或低频操作,直接用 Exec/Query 更轻量,且避免 Stmt 泄漏风险。
立即学习“go语言免费学习笔记(深入)”;
- 不要在循环内反复
db.Prepare—— 每次都新建 Stmt,容易触发"too many connections" - Stmt 本身不是线程安全的,但
*sql.DB是;推荐复用db.Exec等方法,让连接池内部管理预处理 - PostgreSQL 驱动对未命名的
PREPARE有隐式缓存,但 MySQL 驱动(go-sql-driver/mysql)默认关闭 server-side prepare,需显式加parseTime=true&loc=Local参数并确认版本支持
最易被忽略的是连接池配置:SetMaxOpenConns、SetMaxIdleConns、SetConnMaxLifetime 这三个参数不设默认值或设得不合理,会导致连接堆积、DNS 失效未清理、或长连接僵死。特别是云数据库(如 AWS RDS、阿里云 PolarDB)常配置了连接空闲超时,必须让 ConnMaxLifetime 小于该值,否则连接池会持续复用已断开的连接。

















