sqlx不是ORM,只解决结构体自动扫描、命名参数安全传参、RETURNING正确取值三件事;查单行必须用Get而非QueryRow,RETURNING语句必须配Get/Select,命名参数仅PostgreSQL原生支持。

sqlx 不是 ORM,它只解决三件事:结构体自动扫描、命名参数安全传参、RETURNING 正确取值。用错地方或忽略细节,比直接写 database/sql 更容易丢数据。
查单行必须用 Get,别碰 QueryRow
直接调 db.QueryRow 会跳过 sqlx 的 StructScan,字段全为零值还不报错。常见错误包括:
-
db.Get(user, query, args)没加&—— 结构体地址没传进去,字段扫不上 - 结构体字段没写
db:"id"这类 tag,或 tag 值和 SQL 列名/别名不一致(比如 SQL 写SELECT user_name AS name,但 tag 是db:"username") - 字段名大小写混淆:数据库列是
user_id,结构体字段叫UserID,但 tag 写成db:"userid"→ 匹配失败(默认按小写匹配,但别依赖这个)
正确写法:
var user User<br>err := db.Get(&user, "SELECT id, name, email FROM users WHERE id = $1", 123)查不到时返回
sql.ErrNoRows,要用 errors.Is(err, sql.ErrNoRows) 单独判断,别和连接错误混在一起处理。
RETURNING 必须配 Get 或 Select,Exec 会静默丢掉结果
PostgreSQL 的 INSERT ... RETURNING id 看似是增操作,实则是带结果集的查询语句。用 Exec 调用只会丢掉返回值,且不报错——这是最隐蔽的坑。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
- 只取一个字段:
var id int64; err := db.Get(&id, "INSERT INTO users(name) VALUES($1) RETURNING id", "alice") - 取多字段:
type UserWithID struct { ID int64 `db:"id"` Name string `db:"name"` }; var u UserWithID; db.Get(&u, ...) - MySQL/SQLite 不支持
RETURNING,想拿自增 ID 只能靠Result.LastInsertId(),别在 PostgreSQL 里硬套
命名参数只在 PostgreSQL 原生支持,MySQL/SQLite 必须用 Rebind
裸写 :name 在 MySQL 驱动下会 panic,因为 github.com/go-sql-driver/mysql 不识别命名参数。
- PostgreSQL 可直接用:
db.NamedQuery("SELECT * FROM users WHERE name = :name", map[string]interface{}{"name": "alice"}) - MySQL/SQLite 必须先
Rebind:query := sqlx.Rebind(sqlx.POSTGRES, "SELECT * FROM users WHERE name = :name")<br>// 再替换为位置参数,才能传给 MySQL 驱动
- 别手动拼字符串传参,否则 SQL 注入风险拉满;也别指望 sqlx 自动帮你跨驱动兼容
事务中结构体扫描和错误判断要更谨慎
事务内用 Get 或 Select 出错时,不能只看 error 是否为 nil——sql.ErrNoRows 是合法业务态,而连接中断、上下文超时等才是真错误。
- 事务里查不到数据,该回滚还是继续?取决于业务逻辑,不是所有
ErrNoRows都该 abort - 扫描失败(如类型不匹配)会返回具体
sql包错误,比如sql: Scan error on column index 0: unsupported driver -> Scan pair: *string -> *interface{},本质是没让 sqlx 知道目标类型 - 事务提交前务必确认
Get/Select成功,否则可能带着空结构体往下走,后续逻辑崩得无声无息
真正麻烦的从来不是写 SQL,而是字段映射错位、RETURNING 被 Exec 吞掉、命名参数在不同驱动下行为分裂——这些点不盯死,服务跑几天就出不可复现的数据问题。

















