sqlc生成的go代码不能直接用database/sql的scan,因其采用sqlx风格的structscan/scan,要求结构体字段名、类型、顺序与sql列严格匹配,且需正确配置db标签、导出字段及大小写一致。

sqlc 生成的 Go 代码为什么不能直接用 database/sql 的 Scan?
因为 sqlc 默认生成的是结构体(struct)和查询函数,它不依赖 database/sql 的 Scan 接口,而是用 sqlx 风格的 Get/Select 模式——底层调用的是 rows.StructScan 或 row.Scan,但前提是字段名、类型、顺序必须严格匹配。常见错误是:数据库列名含下划线(如 user_id),而 Go 结构体字段用了 UserID,但没加正确的 db 标签,导致扫描失败或字段为零值。
- 确保
sqlc.yaml中启用了emit_json_tags: true和emit_db_tags: true(默认开启) - 结构体字段必须导出(首字母大写),且
db标签值要和 SQL 列名完全一致(区分大小写,除非 DB 是 case-insensitive) - 如果用了
AS别名,比如SELECT name AS full_name,那结构体字段的db标签就得是db:"full_name"
如何让 sqlc 生成带自定义类型(如 uuid.UUID 或 time.Time)的字段?
sqlc 默认把 PostgreSQL 的 UUID 映射为 string,TIMESTAMP 映射为 time.Time —— 看似合理,但实际中常需要更精确的控制,比如强制用 github.com/google/uuid.UUID,或把 TIMESTAMPTZ 统一转成带时区的 time.Time。
- 在
sqlc.yaml的packages下配置overrides,例如:overrides: - db_type: "uuid" go_type: "github.com/google/uuid.UUID" go_imports: - "github.com/google/uuid" - 对时间类型,PostgreSQL 的
timestamptz默认已映射为time.Time,但若发现时区丢失,检查是否漏了timezone=UTC在数据库连接串里 - 自定义类型必须实现
driver.Valuer和sql.Scanner,否则运行时报cannot scan into dest
sqlc generate 报错 “no statements found” 怎么办?
这是最常卡住新手的问题:sqlc 找不到 SQL 文件,或文件里没识别为有效语句。它只认以 -- name: 开头的注释块,且要求格式极其严格。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- SQL 文件必须以
.sql结尾,且放在sqlc.yaml中sql:配置的路径下(如./query/*.sql) -
-- name:必须顶格写,冒号后至少一个空格,后面接函数名 + 空格 + SQL 类型,例如:-- name: GetUser :one - 每条语句之间必须有空行;
:one、:many、:exec必须小写,不能写成ONE或One - 别用 VS Code 的「SQLTools」插件自动加的注释模板,它可能插入了不可见 Unicode 字符
生成的代码里为什么没有 context.Context 参数?
sqlc v1.14+ 默认启用 experimental_context,但旧项目升级后容易忽略这个开关。不带 context 的函数无法超时控制或取消,线上易出长尾请求。
- 确认
sqlc.yaml中version是"2"(不是"1"),且包含:sql: - engine: "postgresql" schema: "schema.sql" queries: "query/" gen: go: package: "db" out: "db" experimental_context: true - 生成后所有查询函数第一个参数都是
ctx context.Context,调用时务必传入非nil上下文,比如ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - 如果已有代码没传
ctx,编译直接报错,没法“悄悄兼容”
真正麻烦的不是生成逻辑,而是 SQL 注释的格式容错率极低,多一个空格、少一个换行,sqlc 就当它不存在。建议把 sqlc generate 加进 CI 的 pre-commit hook 里,早暴露比上线后查半天强。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










