Skip to content

Golang 基础项目配置

Published: at 16:22 UTC+08:00Suggest Changes

主要工具

  1. Docker 运行 postgres 数据库镜像
  2. sqlc 生成类型安全的数据库操作代码
  3. mockgen 在单元测试中模拟 API 行为

从零配置

Go 版本管理

使用 gvm 作为 go 版本管理工具

数据库准备

  1. docker pull postgres:17-alpine 拉取镜像
  2. 执行 docker run --name <container name> -p <port:port> -e <environment> -e ... -d <image> 命令启动容器
  3. 使用 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"

使用

例如,在 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 生成相应的数据库操作代码,非常方便

  1. name 定义了方法名
  2. :<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,
    }
}

Next Post
读 Learn Go with tests 笔记