Golang: sqlc 和 goose 最佳实践

这是在 windows 上的操作示例!!!

参考文档

初始化 golang 项目

1# 创建项目目录
2$ mkdir go-demo
3
4# 进入项目目录
5$ cd go-demo
6
7# 初始化 golang 项目
8$ go mod init go-demo
9go: creating new go.mod: module go-demo

goose 的下载、安装和使用

下载

goose 下载页面: https://github.com/pressly/goose/tags
或者命令行安装: go install github.com/pressly/goose/v3/cmd/goose@latest

注意:如果通过下载的方式,请把可执行文件放到 GOPATH 目录下。

设置数据库连接和脚本生成路径

设置 goose 环境变量(为了后面使用 sqlc 命令生成 golang 代码);
是设置为临时环境变量还是永久环境变量,根据自己的需要。

1# 查看 goose 版本
2$ goose --version
3goose version: v3.27.0
4
5# 设置 goose 数据库连接设置
6$ set GOOSE_DRIVER=postgres
7$ set GOOSE_DBSTRING=postgres://root:123456@localhost:5432/test
8$ set GOOSE_MIGRATION_DIR=./sql/schema

注意: GOOSE_MIGRATION_DIR 表示数据库 DDL 脚本的存储目录。
通过 goose 命令创建 DDL 脚本文件之前,请先创建该目录:mkdir sql\schema

创建 DDL 脚本文件,并生成数据库表

创建 DDL 脚本文件

1$ goose create create_user_table sql
22026/03/20 14:45:38 Created new file: sql\schema\20260320064538_create_user_table.sql

运行上述命令后,会在目录 GOOSE_MIGRATION_DIR 下创建名为 20260320064538_create_user_table.sql 的sql脚本文件。
生成的文件内容大致如下:

1-- +goose Up
2SELECT 'up SQL query';
3
4-- +goose Down
5SELECT 'down SQL query';

编辑上述的脚本文件

大致内容如下:

 1-- +goose Up
 2CREATE TABLE IF NOT EXISTS account
 3(
 4    id       SERIAL PRIMARY KEY,
 5    name     VARCHAR(255) NOT NULL,
 6    email    VARCHAR(255) NOT NULL,
 7    password VARCHAR(255) NOT NULL
 8);
 9
10-- +goose Down
11DROP TABLE IF EXISTS account;

说明:

  • 文件当中的 -- +goose Up-- +goose Down 千万不要删除!
  • -- +goose Up 下面的部分是在执行 goose up 让数据库的版本 +1 的时候生效。
  • -- +goose Down 下面的部分对应的上面部分的反向操作。

上面的 sql 中, goose up 的部分就是在数据库当中创建一张 account 表,而 goose down 的部分就是把数据当中的 account 表删掉。

执行上述的脚本文件

1$ goose up
22026/03/20 16:48:37 OK   20260320064538_create_user_table.sql (8.58ms)
32026/03/20 16:48:37 goose: successfully migrated database to version: 20260320064538
4
5$ goose down
62026/03/20 16:48:51 OK   20260320064538_create_user_table.sql (4.21ms)

说明:

  • goose up : 这个命令能够把当前数据库的版本升级到最新版本,也就是你最新创建的那个数据库迁移文件的版本。
  • goose down :这个命令会将当前的数据库版本进行降低,每次执行都降低一个版本。

即:运行 goose up 后,将会在数据库中创建 account 表;运行 goose down 后,将会在数据库中删除 account 表。

sqlc 的下载、安装和使用

下载

sqlc 下载页面: https://github.com/sqlc-dev/sqlc/tags 或者通过命令行安装:go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest

注意:如果通过下载的方式,请把可执行文件放到 GOPATH 目录下。

生成(或创建)配置文件,并配置

使用下面的命令生成 sqlc 的配置文件:

1$ sqlc init
2sqlc.yaml is added. Please visit https://docs.sqlc.dev/en/stable/reference/config.html to learn more about configuration

亦可直接在项目根目录下创建一个 sqlc.yaml 或者 sqlc.yml 的配置文件。

修改后的内容大致如下:

 1version: "2"
 2sql:
 3  - engine: "postgresql"
 4    queries: "sql/queries"
 5    schema: "sql/schema"
 6    gen:
 7      go:
 8        package: "db"
 9        out: "db"
10        sql_package: "pgx/v5"

上面配置文件中:

  • queries 配置了我需要使用的 SQL 语句所在的目录。
  • schema 配置了数据库表结构,可以直接使用上面 goose 的 schema 。
  • gen 相关的配置就是配置生成的代码的一些信息,package 指定生成代码的包名,out 指定生成代码的文件夹, sql_package 指定生成的代码文件使用的数据库包。

注意,修改上述配置后,记得创建好配置中的 queriesschema(上面已经创建好了)、out 目录:

1$ mkdir sql\queries
2$ mkdir db

创建 crud 的 sql 脚本文件

在 sql\queries 创建名为 user.sql 的 crud sql 脚本文件(文件名随意);大致内容如下:

 1-- name: GetAccountById :one
 2SELECT *
 3FROM account
 4WHERE id = $1 LIMIT 1;
 5
 6-- name: CreateUser :one
 7INSERT INTO account (name, email, password)
 8VALUES ($1, $2, $3) RETURNING *;
 9
10-- name: UpdateUser :exec
11UPDATE account
12SET name = $1, email = $2, password = $3
13WHERE id = $4;
14
15-- name: DeleteUser :exec
16DELETE FROM account
17WHERE id = $1;

简单说明:
每个 SQL 开始之前的注释当中的 name 代表生成的代码当中的方法名,后面的 :one 代表返回一条记录,也可以是多条 :many ,也可以什么也不返回 :exec 。
具体的使用可以参照详细的官方文档。

生成 golang 代码文件

这一步是使用 sqlc 来帮我们生成和数据库交互的相关代码。

1$ sqlc generate

运行上述命令后,会在 db 目录生成对应的 go 文件。

应用上述生成的 golang 代码的示例

在应用的根目录创建 main.go,内容如下:

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"go-demo/db" // 此处导入的就是上面生成的内容
 7	"github.com/jackc/pgx/v5"
 8)
 9
10func main() {
11	conn, _ := pgx.Connect(context.Background(), "postgres://root:123456@localhost:5432/test")
12	defer conn.Close(context.Background())
13	queries := db.New(conn)
14
15	// 创建用户
16	user, _ := queries.CreateUser(context.Background(), db.CreateUserParams{
17		Name:     "Tom",
18		Email:    "tom@gmail.com",
19		Password: "123456",
20	})
21
22	fmt.Println("新增的用户:", user)
23
24	// 查看刚刚创建的用户
25	u1, _ := queries.GetAccountById(context.Background(), user.ID)
26	fmt.Println("查看用户信息:", u1)
27
28	// 更新用户信息
29	_ = queries.UpdateUser(context.Background(), db.UpdateUserParams{
30		Name:     "Thomas",
31		Email:    "tom@gmail.com",
32		Password: "888888",
33		ID:       user.ID,
34	})
35
36	// 查看更新后的用户信息
37	u2, _ := queries.GetAccountById(context.Background(), user.ID)
38	fmt.Println("更新后的用户信息:", u2)
39
40	// 删除用户
41	// _ = queries.DeleteUser(context.Background(), user.ID)
42
43	// 查看已删除的用户,打印发现 user.ID = 0,表示该用户已被删除
44	// u3, _ := queries.GetAccountById(context.Background(), user.ID)
45	// fmt.Println(u3)
46}

使用命令导入依赖: go get github.com/jackc/pgx/v5,然后运行: go run main.go,结果如下:

1$ go run main.go
2新增的用户: {1 Tom tom@gmail.com 123456}
3查看用户信息: {1 Tom tom@gmail.com 123456}
4更新后的用户信息: {1 Thomas tom@gmail.com 888888}