go-sqlc-typed-queries
test12026-10-2615 次阅读
传统写法的痛点
用 database/sql 手写查询,结果要一行行 rows.Scan 到变量,列名拼错、类型对不上只能在运行期爆。sqlc 反其道而行:你写普通的 SQL,它在编译期生成类型安全的 Go 代码,字段、参数、返回行全部有类型,改了表结构重新生成就能发现调用方哪里没跟上。
定义 schema 与查询
schema.sql 描述表结构,queries.sql 写业务 SQL,每条查询用注释起一个名字,并标注返回一行还是多行。
-- schema.sql
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
bio TEXT NOT NULL
);
CREATE TABLE books (
id BIGSERIAL PRIMARY KEY,
author_id BIGINT NOT NULL REFERENCES authors(id),
title TEXT NOT NULL,
price_cents BIGINT NOT NULL
);
-- queries.sql
-- name: GetAuthor :one
SELECT id, name, bio FROM authors WHERE id = $1;
-- name: ListBooksByAuthor :many
SELECT id, author_id, title, price_cents
FROM books
WHERE author_id = $1
ORDER BY title;
-- name: CreateBook :one
INSERT INTO books (author_id, title, price_cents)
VALUES ($1, $2, $3)
RETURNING id, author_id, title, price_cents;
配置 sqlc.yaml
指定引擎、schema、queries 与输出目录,sql_package 选 pgx/v5 可以直连连接池。
version: "2"
sql:
- engine: "postgresql"
queries: "queries.sql"
schema: "schema.sql"
gen:
go:
package: "db"
out: "internal/db"
sql_package: "pgx/v5"
emit_json_tags: true
生成后怎么用
运行 sqlc generate,它会产出 Book、Author 结构体以及带参数的查询方法。调用方拿到的全是强类型,价格这类字段也不会被误当成浮点。
package main
import (
"context"
"log"
"github.com/jackc/pgx/v5/pgxpool"
"example.com/app/internal/db"
)
func main() {
ctx := context.Background()
pool, _ := pgxpool.New(ctx, "postgres://user:pass@localhost:5432/books")
queries := db.New(pool)
book, err := queries.CreateBook(ctx, db.CreateBookParams{
AuthorID: 1,
Title: "The Pragmatic Programmer",
PriceCents: 3999,
})
if err != nil {
log.Fatal(err)
}
log.Println(book.ID, book.Title, book.PriceCents)
books, _ := queries.ListBooksByAuthor(ctx, 1)
log.Println(len(books))
}
收益与注意点
- 字段类型由数据库方言推断,避免 Scan 到错类型在运行期才炸。
- SQL 仍是手写,索引、连表优化完全掌控,不丢灵活性。
- nullable 列会生成 pgtype 类型,需要额外处理,建表时能用 NOT NULL 就别留空。
- CI 里加一步 sqlc diff 或 sqlc vet,SQL 和生成代码不一致就直接红。
T
test1
文章作者
传统写法的痛点 用 database/sql 手写查询,结果要一行行 rows.Scan 到变量,列名拼错、类型对不上...
- 分类
- 技术
- 发布时间
- 2026-10-26
- 字数
- 约 1962 字
- 阅读
- 15 次
