goctl model 命令详解

「go-zero 生成 Model 的命令到底有哪些参数、怎么用、生成的文件都是啥?」—— 这篇把 goctl model 的 mysql / pg / mongo 三类数据源、每个 flag 的含义与默认值、典型命令组合、以及生成出来的每一个文件逐一点清。配命令速查表,适合直接贴终端用。

一句话结论 命令全景 mysql ddl mysql datasource pg / mongo 生成了啥 参数速查 典型用法 踩坑 与 api/rpc 对比

goctl model = 「读表结构 → 生成数据访问代码」

它不建表(呼应 建表与 Model 流程),只根据「DDL 文件」或「活的数据库连接」批量产出 model 包。

命令形态是 goctl model <数据源> <子命令>数据源mysql / pg / mongomysql 下又有两条子命令——ddl(从 SQL 文件生成)和 datasource(从已建好的库反查生成)。两条路产物完全一样,区别只在信息源。两篇相邻主题:建表与 Model 流程后端开发完整流程

goctl model 的子命令树

记住这张图,就知道该用哪条命令。

goctl model ├── mysql # MySQL(最常用) │ ├── ddl # 输入:.sql 建表文件(支持 glob *.sql) │ └── datasource # 输入:活的数据库连接(按表名反查) ├── pg # PostgreSQL │ └── datasource # 从库反查(pg 无 ddl 子命令) └── mongo # MongoDB └── datasource # 从集合反查(无缓存概念)
信息源 .sql / 数据库 goctl model 读结构→生成代码 mysql.ddl 从 SQL 文件 mysql.datasource 从活库反查 model/ 包代码
本篇只讲 命令与参数。生成出来的 Model 怎么注入 svc、在 logic 里调用、缓存怎么工作,见 建表与 Model 流程 的「接入 svc / logic 使用 / 缓存」三节。

从 SQL 文件生成:goctl model mysql ddl

适合「表结构已经写成 .sql 文件」的场景,文件可纳入版本管理。

最小可用命令

goctl model mysql ddl \
  --src user.sql \     # 必填:DDL 文件(支持 glob 模式 *.sql)
  --dir ./model \      # 输出目录,默认 ./model
  --cache             # 可选:生成 Redis 缓存代码

参数逐个讲

参数简写默认必填作用
--src-s必填DDL 文件路径,或 glob 模式*.sql./sql/*.sql)。可传多个文件 / 多个 --src
--dir-d./model可选生成代码的输出目录,目录不存在会自动创建
--cache-cfalse可选是否生成带 Redis 缓存的 Model(主键 / 单字段唯一索引查询自动加缓存)
--stylegozero可选生成文件命名风格:gozero(连写小写)/ go_zero(蛇形下划线)等,见 --style 区别
--ideafalse可选生成 IDEA 插件兼容格式(老式 goctl idea 插件用,日常基本不用)
--database--db可选指定数据库名。当 DDL 里没写库名、或一份 SQL 跨多个库生成时用
--home可选本地模板目录;自定义生成代码风格用(与 --remote 互斥,同时设以 remote 为准)
--remote可选远程 git 模板仓库地址(如 https://github.com/zeromicro/go-zero),用于拉取自定义模板
--branchmaster可选远程模板的分支名(配 --remote 用)
--force版本相关可选较新版本支持:目标文件已存在时直接覆盖、不弹确认。老版本需手动删旧文件
--src 支持 glob 模式--src ./*.sql 一次吃下当前目录所有 SQL;--src user.sql order.sql 多个文件也可。但 goctl 仍不执行建表——它只「读」SQL 里的 CREATE TABLE 来推结构,表得你自己先 mysql < user.sql 落到库里(或交给迁移工具)。

从活库反查:goctl model mysql datasource

适合「表已经在数据库里了」,连上去直接按表名生成,连 SQL 文件都不用准备。

最小可用命令

goctl model mysql datasource \
  --url "root:password@tcp(127.0.0.1:3306)/test" \  # 必填:数据源
  --table user \          # 必填:表名(支持逗号分隔、glob)
  --dir ./model \         # 可选:输出目录
  --cache                # 可选:带缓存

参数逐个讲

参数简写默认必填作用
--url必填数据源连接串,格式 user:password@tcp(host:port)/dbname。需有该库的 读表结构权限(SELECT 元信息)
--table-t必填表名。支持 逗号分隔user,order)与 glob 模式user_*);可多次 --table
--dir-d./model可选输出目录
--cache-cfalse可选生成带 Redis 缓存的 Model(同 ddl)
--stylegozero可选文件命名风格(同 ddl)
--ideafalse可选IDEA 插件兼容格式(同上,基本不用)
--home / --remote / --branch / --force可选模板自定义 / 覆盖,含义与 ddl 完全一致
--table 的两种玩法
逗号分隔:--table user,order 一次生成两张;glob:--table "user_*" 吃掉所有 user_ 前缀表。两种可混用。
ddl 与 datasource 的差异
ddl 读 SQL 文件、datasource 读 活库;必填项不同(src vs url+table);输出代码一模一样。
没有单独的 --tables 参数——多表用 --table逗号分隔多次 --table 表达,或 glob 模式一次性匹配。网上有些旧资料写 --tables,以官方 -h 输出为准。

另外两类数据源:PostgreSQL 与 MongoDB

goctl 也支持,但形态略有不同(都是 datasource 反查,没有 ddl 子命令)。

PostgreSQL · goctl model pg datasource

goctl model pg datasource \
  --url "postgres://user:pass@127.0.0.1:5432/test?sslmode=disable" \
  --table users \       # 表名;pg 有 schema 概念,默认 public
  --dir ./model \
  --cache              # pg 同样支持缓存(主键/唯一索引)

pg 子命令几乎复用 mysql 的参数(--url --table --dir --cache --style),连接串换成 Postgres 格式;没有 ddl 子命令,只能从活库生成。

MongoDB · goctl model mongo datasource

goctl model mongo datasource \
  --url "mongodb://127.0.0.1:27017" \
  --table articles \    # 集合名
  --dir ./model \
  --style gozero

Mongo 是文档库,没有「表 / 缓存」概念,因此无 --cache;生成的是基于 core/stores/mongo 的文档增删改查。参数随版本略有差异,以 goctl model mongo datasource -h 为准。

mysql 是 go-zero 支持最完整、文档最全的数据源;pg / mongo 属于「能用但细节随版本变」,生成前务必跑一次 goctl model pg datasource -h / goctl model mongo datasource -h 看当前版本真实参数,别照搬 mysql 的 flag。

生成出来的 model 包都有啥

无论 ddl 还是 datasource,--dir 下都会冒出这批文件。理解角色才不会手改错地方。

model/ ├── types.go # 结构体:列 → 字段映射(带 db 标签) ├── vars.go # 缓存 key 前缀、表名等常量 ├── errors.go # ErrNotFound 等 ├── usermodel.go # 接口定义 + 自定义方法(手写区) └── usermodel_gen.go # CRUD 真实实现(自动生成,别手改!)
文件内容重生成会覆盖吗
types.go每个表一个结构体,字段带 db:"create_time" 标签;snake_case 列自动对应 CamelCase 字段,按表结构刷新
vars.go缓存 key 前缀(cacheUserPrefix 等)+ 表名常量。开 --cache 才有缓存前缀,否则只有表名
errors.goErrNotFound——查不到记录时返回的错误
usermodel.go定义 UserModel 接口、声明 customUserModel 内嵌 defaultUserModel你写的自定义查询方法放这里接口签名刷新;手写方法保留
usermodel_gen.goInsert / FindOne / FindOneByName / Update / Delete 等基础 CRUD 的真实实现 + 缓存逻辑,全在文件里,整个文件被重写

生成规则(决定「自带哪些方法」)

主键 → 基础 CRUD
有主键就生成 FindOne / Insert / Update / Delete
二级索引 → FindOneByXxx
每个 KEY idx_xxx(col) 额外生成 FindOneByName 之类;索引写得越全,自带查询越多。
--cache 作用范围
只给主键 / 单字段唯一索引查询加缓存;联合索引默认不带缓存(go-zero 认为非通用)。
createTime / updateTime
默认插入、更新时不赋值这两个字段(由 DB 的 CURRENT_TIMESTAMP 管),生成代码已排除。
铁律:自定义查询(聚合、连表、复杂 WHERE)写在 usermodel.go千万别写进 usermodel_gen.go——下次重跑 goctl 整个文件被覆盖,代码瞬间消失。约定:生成的归 _gen.go,手写的归 usermodel.go

所有参数一表汇总

直接贴终端对照用。⊕=必填,○=可选。

参数简写默认ddldatasource含义
--src-sDDL 文件 / glob 模式
--url数据源连接串
--table-t表名(逗号 / glob / 多次)
--dir-d./model输出目录
--cache-cfalse生成 Redis 缓存代码
--stylegozero文件命名风格
--ideafalseIDEA 插件兼容
--database--db指定库名(ddl 跨库用)
--home本地模板目录
--remote远程模板仓库
--branchmaster远程模板分支
--force版本相关覆盖已存在文件不询问
两套「公共可选参数」完全一致:--dir --cache --style --idea --home --remote --branch --force。差异只在信息源相关的必填项——ddl 要 --src,datasource 要 --url + --table

几条直接能抄的命令

从「第一次生成」到「加表 / 改表后重生成」。

① 首次:一份 SQL 生成带缓存的 Model

goctl model mysql ddl --src ./*.sql --dir ./internal/model --cache --style gozero

② 首次:连上已建好的库,只生成两张表

goctl model mysql datasource \
  --url "root:123456@tcp(127.0.0.1:3306)/test" \
  --table user,order \
  --dir ./internal/model \
  --cache

③ 加表:库中新增了 pay 表,补生成

goctl model mysql datasource \
  --url "root:123456@tcp(127.0.0.1:3306)/test" \
  --table pay --dir ./internal/model --cache

新表文件会加进来,旧表文件不受影响(已手改的 usermodel.go 自定义方法保留)。

④ 改表:把 user 加了一列,重生成

# 老版本先删旧文件,再生成;新版本加 --force 直接覆盖
goctl model mysql datasource \
  --url "root:123456@tcp(127.0.0.1:3306)/test" \
  --table user --dir ./internal/model --cache --force
改表后必须重生成否则代码用旧字段;重生成会覆盖 _gen.gotypes.go,但只要你的自定义逻辑在 usermodel.go 就安全。

六个最容易翻车的地方

现象正确做法
以为 goctl 建表连空库生成报「表不存在」先建表(SQL / 迁移工具),再生成代码
--cache 却没配 Redis启动报错缺 CacheRedisconfig 加 CacheRedis redis.RedisConf 并配地址(呼应 Model 流程·缓存
datasource 权限不够连库成功但读不到表结构用有 information_schema 读权限的账号
忘了加二级索引没有 FindOneByXxx建表时把常用查询列写成 KEY idx_xxx
手改 _gen.go重生成后代码消失自定义只写 usermodel.go
照搬 mysql 参数到 pg/mongoflag 报错各数据源先跑 -h 看真实参数

goctl model 与 api / rpc 命令的差异

都是 goctl 的子命令,但「信息源」与「必填项」不同。

命令信息源必填项产出
goctl model mysql ddl.sql 文件--srcmodel 包(数据访问)
goctl model mysql datasource活库--url --tablemodel 包(数据访问)
goctl api go.api 文件--apihandler/logic/types/svc 骨架
goctl rpc protoc.proto 文件--src --go_outpb.go / zrpc 服务端客户端
共性:都是「声明式契约 + 代码生成」,你写源文件、goctl 吐骨架、你只在 logic / usermodel.go 填业务。区别在源文件类型与产物层级——model 只负责数据访问层,api/rpc 负责接口与传输层。完整串联见 后端开发完整流程

记牢:goctl model 不建表,只「读表生成代码」;ddl 吃 SQL 文件、datasource 吃活库;两套公共参数(dir/cache/style/idea/home/remote/branch/force)完全一样;产物是 types/vars/errors/usermodel.go/usermodel_gen.go 五个文件,自定义逻辑写 usermodel.go