sqlx.queryrowx比database/sql更省事,因其能按字段名自动映射查询结果到结构体,免去手动scan;但需结构体字段带正确db tag(如db:"id"),否则静默置零而非报错。

sqlx.QueryRowx 为什么比 database/sql 更省事
因为 sqlx.QueryRowx 能直接把查询结果按字段名自动塞进结构体字段,不用手动调 Scan 一长串变量。前提是结构体字段有正确的 db tag,比如 type User struct { ID int `db:"id"` Name string `db:"name"` }。漏写 tag 或拼错字段名,就会静默忽略对应字段——不是报错,是值保持零值,这点特别容易排查半天才发现是 tag 写成了 `db:"Id"`(大小写不匹配)。
常见错误现象:QueryRowx(&u).Err() 返回 nil,但 u.Name 是空字符串。此时先检查数据库返回的列名是否真叫 name(比如用了 SELECT u_name AS name 就没问题,但写成 SELECT u_name 就会映射失败)。
- 别依赖 SELECT *,显式写出字段名,避免表结构变更后字段顺序错位
- 如果字段名含下划线(如
created_at),结构体字段可用CreatedAt+db:"created_at",sqlx 默认开启DBMapper支持蛇形转驼峰,但建议显式声明更可控 - 空值处理:
sql.NullString等类型必须用对应字段类型接收,不能直接用string,否则 Scan 会报sql: Scan error on column index 1
sqlx.Select 与结构体切片的批量映射陷阱
sqlx.Select 看似一行搞定查多行,但实际运行时可能因字段缺失、类型不匹配或空结果集导致 panic 或数据截断。它底层调的是 reflect,对结构体字段权限敏感——首字母小写的字段(如 id int)根本不会被赋值,且无任何提示。
使用场景:适合固定 schema 的读取,比如 SELECT id, name FROM users WHERE status = ?。不适合动态列或 UNION 查询结果。
Colly 是一个用于 Go 语言的快速开源爬取和爬虫框架。它适用于从简单的页面提取到异步爬虫处理大量页面集合,支持请求回调和结构化解析。
- 确保结构体所有要映射的字段都是导出字段(大写开头)
- 如果某次查询只返回部分字段(比如只查
id),其他字段会保持零值,不会清空之前的数据——所以别复用同一个切片做多次不同字段的Select - 性能上,
Select比手动循环Query+StructScan略慢一点,但可读性高;高频小查询(如单条配置)用QueryRowx更合适
NamedExec 和 NamedQuery 中 :name 占位符的实际限制
NamedQuery 允许你用 :name 写 SQL,再传 map 或结构体当参数,看着很干净。但它不支持嵌套结构体字段展开,比如 user.Profile.Email 这种写法在 SQL 里会直接报错“unknown field”。只能扁平化传参:map[string]interface{}{"email": u.Profile.Email}。
错误现象:sql: expected 1 arguments, got 2,往往是因为传了结构体但 SQL 里写了两个 :xxx,而结构体里只有 1 个匹配字段——sqlx 不会补默认值,少一个就报错。
- 命名参数只认顶层字段或 map key,不递归解析
- 数组参数(如
IN (?))要用sqlx.In配合Rebind,不能直接写IN (:ids) - PostgreSQL 用户注意:
NamedQuery默认生成$1, $2形式占位符,如果手写 SQL 用了$1又混用:name,会冲突报错
事务中 sqlx 结构体映射的生命周期问题
在 tx := db.Beginx() 后,所有 tx.Queryx、tx.Get 行为都共享同一事务上下文,但结构体本身没事务概念。容易被忽略的是:如果事务中途 rollback,之前已成功 Get 到的结构体变量仍是有效数据,不会自动回滚或置空——这和 ORM 的 session 机制完全不同。
这意味着你不能假设“查出来的结构体一定代表数据库当前一致状态”,尤其在并发更新频繁的场景。
- 事务内多次查询同一条记录,应重新
Get,不要复用之前查到的结构体指针去改字段再Update - 如果用
StructScan手动扫描,注意它不校验字段是否全映射,缺字段也不会报错,容易掩盖逻辑 bug - sqlx 本身不提供乐观锁支持,
UPDATE ... WHERE version = ?这类操作得自己加字段、自己判影响行数










