主要工具
- Docker 运行 postgres 数据库镜像
- sqlc 生成类型安全的数据库操作代码
- mockgen 在单元测试中模拟 API 行为
从零配置
Go 版本管理
使用 gvm 作为 go 版本管理工具
数据库准备
docker pull postgres:17-alpine
拉取镜像- 执行
docker run --name <container name> -p <port:port> -e <environment> -e ... -d <image>
命令启动容器 - 使用 TablePlus 应用连接数据库
docker run --name postgres17 -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:17-alpine
在 makefile 中新增一条 db 命令,方便重启设备之后快速开始开发
# 启动 db
db:
@echo "Starting db..."
@docker run -d --name postgres17 \
--restart=always \
-p 5432:5432 \
-e POSTGRES_USER=greenlight \ # 用户名
-e POSTGRES_PASSWORD=pa55word \ # 数据库密码
-e POSTGRES_DB=greenlight \ # 自定义数据库
-v postgres_data:/var/lib/postgresql/data \ # 持久化存储数据
postgres:17-alpine
@echo "Db started."
通过 docker volume ls
查看所有容器 volume 挂载
Database schema migrate
使用 Golang migrate 管理和执行数据库迁移,在新项目中,执行下面的命令,创建 migration
migrate create -ext sql -dir db/migration -seq init_schema
执行完成后会创建两个迁移文件。在 *.up.sql 文件中填写对数据表的修改,在 *.down.sql 文件中填写回滚操作。通过 migrate 提供的 up 和 down 命令,执行数据库的更新和回滚操作。
sqlc 生成代码
使用 sqlc 来辅助生成数据库增删改查的代码。
安装
使用 homebrew 安装 sqlc
brew install sqlc
之后在项目根目录下创建 sqlc.yaml
配置文件,最简配置如下。推荐将所有数据库操作的文件统一放在 db 目录下
version: "2"
servers: []
sql:
- schema: "db/migration"
engine: "postgresql"
queries: "db/query"
gen:
go:
package: "db"
out: "db/sqlc"
sql_package: "database/sql"
emit_json_tags: true
emit_interface: true
emit_empty_slices: true
overrides:
- db_type: "timestamptz"
go_type: "time.Time"
使用
- schema 指定了 sqlc 生成数据类型代码的 SQL 文件目录
- queries 指定了放置查询 sql 文件的目录
例如,在 db/query 目录下,添加 movies.sql 并添加如下两个 sql 语句
-- name: ListMovies :many
SELECT *
FROM movies
WHERE title = $1
ORDER BY id
LIMIT $2 OFFSET $3;
-- name: CreateMovie :one
INSERT INTO movies (title, year, runtime, genres)
VALUES ($1, $2, $3, $4)
RETURNING *;
接下来执行 sqlc generate
生成相应的数据库操作代码,非常方便
name
定义了方法名:<mode>
定义了该语句的 mode,还有下面几种常用的 mode
模式 | 描述 |
---|---|
:one | 返回一行一列,或一行数据结构(struct) |
:many | 返回多行结果,Go 里就是 []T |
:exec | 用于不返回结果的执行语句,比如 INSERT/UPDATE/DELETE |
:execrows | 返回 sql.Result.RowsAffected(),获取影响行数 |
:copyfrom | 用于 PostgreSQL 的 COPY FROM 批量插入(性能高) |
:batch | 生成 Stmt.ExecContext 的批处理函数 |
数据库 Mock
使用 gomock 搭配提供的 mockgen 命令行工具,可以根据 API 定义快速生成 mock 代码。
搭配 sqlc 使用的话,可以封装一层 Store 接口
import "database/sql"
type Store interface {
Querier
}
type SQLStore struct {
*Queries
db *sql.DB
}
func NewStore(db *sql.DB) Store {
return &SQLStore{
Queries: New(db),
db: db,
}
}