database/sql 是接口规范,需搭配驱动使用;sql.Open 不建连,须用 db.Ping() 校验;Query 用于多行需手动 Close,QueryRow 用于单行自动关闭;防注入须用占位符;事务须配对 Commit/Rollback;连接池参数需调优。

直接用 database/sql 无法执行任何数据库操作——它只是接口规范,必须搭配驱动(如 github.com/go-sql-driver/mysql 或 github.com/lib/pq)才能工作。
为什么 sql.Open 不报错却连不上数据库?
sql.Open 只是初始化连接池配置,并不真正建连。真实校验要靠 db.Ping()。
- 常见错误现象:
sql.Open返回nilerror,但后续Query报"sql: database is closed"或超时 - 正确做法:初始化后立刻调用
db.Ping()并检查 error - 注意:
db.Ping()是同步阻塞的,生产环境建议加 context 控制超时,例如db.PingContext(ctx, time.Second*5)
Query 和 QueryRow 的核心区别在哪?
本质是结果集数量预期不同,影响资源释放逻辑和 panic 风险。
-
Query用于多行结果(如 SELECT 多条记录),返回*sql.Rows,必须显式调用rows.Close(),否则连接不会归还池中 -
QueryRow用于单行结果(如 SELECT ... LIMIT 1 或聚合函数),内部自动 close,但若实际无结果会返回sql.ErrNoRows,不处理就 panic - 别用
QueryRow去查可能返回多行的数据——它只读第一行,其余被丢弃且不报错
怎么安全传参避免 SQL 注入?
永远用 ? 占位符 + 参数列表,不要字符串拼接。
采用HttpClient向服务器端action请求数据,当然调用服务器端方法获取数据并不止这一种。WebService也可以为我们提供所需数据,那么什么是webService呢?,它是一种基于SAOP协议的远程调用标准,通过webservice可以将不同操作系统平台,不同语言,不同技术整合到一起。 实现Android与服务器端数据交互,我们在PC机器java客户端中,需要一些库,比如XFire,Axis2,CXF等等来支持访问WebService,但是这些库并不适合我们资源有限的android手机客户端,
立即学习“go语言免费学习笔记(深入)”;
- MySQL 驱动用
?,PostgreSQL 驱动用$1,$2,SQLite 两者都支持但推荐? - 错误写法:
db.Query("SELECT * FROM users WHERE name = '" + name + "'")—— 直接引入注入风险 - 正确写法:
db.Query("SELECT * FROM users WHERE name = ?", name) - 注意:占位符不能用于表名、列名或 ORDER BY 子句,这些需白名单校验后拼接
事务里忘了 Rollback 会怎样?
连接会一直被事务占用,直到超时或进程退出,最终拖垮连接池。
- 典型陷阱:只写了
tx.Commit(),但没在 defer 或 else 分支里配对tx.Rollback() - 推荐模式:
defer func() { if r := recover(); r != nil { tx.Rollback() } }()+ 显式if err != nil { tx.Rollback(); return } - 更稳妥的做法:用
tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadCommitted}),支持 context 取消
最易被忽略的是连接池行为:默认 MaxOpenConns=0(无限制)、MaxIdleConns=2,高并发下很容易耗尽数据库连接数。上线前务必根据 DB 实例规格调优这两个值。









