Skip to main content

goctl model

概述

goctl model 为 goctl 提供的数据库模型代码生成指令,目前支持 MySQL、PostgreSQL、Mongo 的代码生成,MySQL 支持从 sql 文件和数据库连接两种方式生成,PostgreSQL 仅支持从数据库连接生成。

goctl model 指令

$ goctl model  --help
Generate model code

Usage:
goctl model [command]

Available Commands:
mongo Generate mongo model
mysql Generate mysql model
pg Generate postgresql model

Flags:
-h, --help help for model


Use "goctl model [command] --help" for more information about a command.

goctl model mongo 指令

Mongo 的生成不同于 MySQL,MySQL 可以从 scheme_information 库中读取到一张表的信息(字段名称,数据类型,索引等), 而 Mongo 是文档型数据库,我们暂时无法从 db 中读取某一条记录来实现字段信息获取,就算有也不一定是完整信息(某些字段可能是 omitempty 修饰,可有可无), 这里采用 type 自己编写+代码生成方式实现。

$ goctl model mongo --help
Generate mongo model

Usage:
goctl model mongo [flags]

Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --cache Generate code with cache [optional]
-d, --dir string The target dir
-e, --easy Generate code with auto generated CollectionName for easy declare [optional]
-h, --help help for mongo
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
-t, --type strings Specified model type name
参数字段 参数类型 是否必填 默认值 参数说明
branchstringNO空字符串远程模板所在 git 分支名称,仅当 remote 有值时使用
cachebooleanNOfalse是否生成带缓存的代码
dirstringNO当前工作目录代码输出目录
easybooleanNOfalse是否暴露集合名称变量
homestringNO${HOME}/.goctl本地模板文件目录
remotestringNO空字符串远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值
stylestringNOgozero输出文件和目录的命名风格格式化符号,详情见 文件风格
type[]stringYESnil结构体类型名称

使用示例

以下我们以生成一个 User 结构体为例。

示例 1: 生成带缓存的代码

# 进入用户 Home 目录
$ cd ~

# 创建 demo 目录
$ mkdir demo && cd demo

# 生成 mongo 代码
$ goctl model mongo --type User --dir cache --cache

# 查看目录结构
$ tree
.
└── cache
├── error.go
├── usermodel.go
├── usermodelgen.go
└── usertypes.go

1 directory, 4 files

查看代码

package model

import (
"errors"

"github.com/zeromicro/go-zero/core/stores/mon"
)

var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)

示例 2: 生成不带缓存的代码

# 进入用户 Home 目录
$ cd ~

# 创建 demo 目录
$ mkdir demo && cd demo

# 生成 mongo 代码
$ goctl model mongo --type User --dir nocache

# 查看目录结构
$ tree
.
└── nocache
├── error.go
├── usermodel.go
├── usermodelgen.go
└── usertypes.go

1 directory, 4 files

查看代码

package model

import (
"errors"

"github.com/zeromicro/go-zero/core/stores/mon"
)

var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)

新增自定义 model 方法示例

在以上代码生成中可以看出,每张表生成都会有 4 个文件,其中 xxmodel.goxxmodelgen.go 是 model 代码文件,待有 gen.go 文件后缀的 代码一般都会包含 DO NOT EDIT 标识,因此不能在这个文件中添加自定义代码,当用户需要新增或者修改代码时,可以在 xxmodel.go 中进行编辑, 在 xxmodel.go 中我们提供了 customXXXModel 结构体便于开发者进行扩展,这里接着上文生成的无缓存代码作为示例,我们给 user 表新增一个 List 方法。

  1. 编辑 usermodel.go 文件
  2. UserModel 接口中新增方法 List(ctx context.Context, page, limit int) ([]*User, error)
  3. 实现 customUserModel

最终代码如下,灰色底纹部分为新增自定义新增内容

package nocache

import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ UserModel = (*customUserModel)(nil)

type (
// UserModel is an interface to be customized, add more methods here,
// and implement the added methods in customUserModel.
UserModel interface {
userModel
List(ctx context.Context, page, limit int) ([]*User, error)
}

customUserModel struct {
*defaultUserModel
}
)

func (c *customUserModel) List(ctx context.Context, page, limit int) ([]*User, error) {
query := fmt.Sprintf("select %s from %s limit ?,?", userRows, c.table)
var resp []*User
err := c.conn.QueryRowsCtx(ctx, &resp, query, (page-1)*limit, limit)
return resp, err
}

// NewUserModel returns a model for the database table.
func NewUserModel(conn sqlx.SqlConn) UserModel {
return &customUserModel{
defaultUserModel: newUserModel(conn),
}
}

忽略字段控制

在 goctl 代码生成逻辑中,生成后的代码会在执行插入或者更新操作时会忽略某些字段的赋值,如 create_timeUpdate_time 等,目前 goctl 默认内置了 create_at, create_time, created_at, update_at, update_time, updated_at) 字段,在某些场景下 开发者可能不需要忽略,或者忽略的字段名称不为这些,开发者可以通过 --ignore-columns (-i) 进行控制,当 --ignore-columns (-i) 传值为空时 则跳过对 column 进行忽略,如果需要指定某些字段,则传具体值即可。

  • 示例 1:跳过 column 忽略
# 必须显示传值为空字符串
$ goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/ignore_columns/cache" -i ''
...
var (
studentFieldNames = builder.RawFieldNames(&Student{})
studentRows = strings.Join(studentFieldNames, ",")
studentRowsExpectAutoSet = strings.Join(stringx.Remove(studentFieldNames), ",")
studentRowsWithPlaceHolder = strings.Join(stringx.Remove(studentFieldNames, "`type`"), "=?,") + "=?"
)
...
  • 示例 2:指定某些 column 忽略
...
var (
studentFieldNames = builder.RawFieldNames(&Student{})
studentRows = strings.Join(studentFieldNames, ",")
studentRowsExpectAutoSet = strings.Join(stringx.Remove(studentFieldNames, "`column1`", "`column2`"), ",")
studentRowsWithPlaceHolder = strings.Join(stringx.Remove(studentFieldNames, "`type`", "`column1`", "`column2`"), "=?,") + "=?"
)
...
# --ignore-columns 支持通过英文逗号分割的字符串来传多个值,也支持指定多个参数来传多个只
$ goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/ignore_columns/cache" -i 'column1,column2'
# 以上 shell 等同于
$ goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/ignore_columns/cache" -i 'column1' -i "column2"

goctl model mysql 指令

goctl model mysql 指令用于生成基于 MySQL 的 model 代码,支持生成带缓存和不带缓存的代码。MySQL 代码生成支持从 sql 文件,数据库连接两个来源生成代码。

$ goctl model mysql --help
Generate mysql model

Usage:
goctl model mysql [command]

Available Commands:
datasource Generate model from datasource
ddl Generate mysql model from ddl

Flags:
-h, --help help for mysql
-i, --ignore-columns strings Ignore columns while creating or updating rows (default [create_at,created_at,create_time,update_at,updated_at,update_time])
--strict Generate model in strict mode


Use "goctl model mysql [command] --help" for more information about a command.

goctl model mysql datasource 指令

goctl model mysql datasource 指令用于从数据库连接生成 model 代码。

$ goctl model mysql datasource --help
Generate model from datasource

Usage:
goctl model mysql datasource [flags]

Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --cache Generate code with cache [optional]
-d, --dir string The target dir
-h, --help help for datasource
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--idea For idea plugin [optional]
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
-t, --table strings The table or table globbing patterns in the database
--url string The data source of database,like "root:password@tcp(127.0.0.1:3306)/database"


Global Flags:
-i, --ignore-columns strings Ignore columns while creating or updating rows (default [create_at,created_at,create_time,update_at,updated_at,update_time])
--strict Generate model in strict mode
参数字段 参数类型 是否必填 默认值 参数说明
branchstringNO空字符串远程模板所在 git 分支名称,仅当 remote 有值时使用
cachebooleanNOfalse是否生成带缓存的代码
dirstringNO当前工作目录代码输出目录
easybooleanNOfalse是否暴露集合名称变量
homestringNO${HOME}/.goctl本地模板文件目录
remotestringNO空字符串远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值
stylestringNOgozero输出文件和目录的命名风格格式化符号,详情见 文件风格
table[]stringYESnil需要生成代码的表
urlstringYES空字符串数据库连接,格式{{username}}:{{password}}@tcp({{host_port}})/{{db}}
ignore-columns[]stringNOnil需要忽略的字段,插入或者更新时需要忽略的字段,如 create_time
strictbooleanNOfalse是否是严格模式,如果是严格模式下,会对 unsigned 修饰的字段转换为对应的数据类型,主要针对数值型,例如:如果数据库中列为 bigint 类型,如果为unsigned 修饰则对应的 golang 数据类型就为 int64,否则为 uint64,如果 strict 为 false,则不关注 unsigned 修饰

goctl model mysql ddl 指令

goctl model mysql ddl 指令用于从 sql 文件生成 model 代码。

$ goctl model mysql ddl --help
Generate mysql model from ddl

Usage:
goctl model mysql ddl [flags]

Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --cache Generate code with cache [optional]
--database string The name of database [optional]
-d, --dir string The target dir
-h, --help help for ddl
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--idea For idea plugin [optional]
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
-s, --src string The path or path globbing patterns of the ddl
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]


Global Flags:
-i, --ignore-columns strings Ignore columns while creating or updating rows (default [create_at,created_at,create_time,update_at,updated_at,update_time])
--strict Generate model in strict mode
参数字段 参数类型 是否必填 默认值 参数说明
branchstringNO空字符串远程模板所在 git 分支名称,仅当 remote 有值时使用
cachebooleanNOfalse是否生成带缓存的代码
dirstringNO当前工作目录代码输出目录
easybooleanNOfalse是否暴露集合名称变量
homestringNO${HOME}/.goctl本地模板文件目录
remotestringNO空字符串远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值
srcstringYES空字符串sql 文件路径
stylestringNOgozero输出文件和目录的命名风格格式化符号,详情见 文件风格
ignore-columns[]stringNOnil需要忽略的字段,插入或者更新时需要忽略的字段,如 create_time
strictbooleanNOfalse是否是严格模式,如果是严格模式下,会对 unsigned 修饰的字段转换为对应的数据类型,主要针对数值型,例如:如果数据库中列为 bigint 类型,如果为unsigned 修饰则对应的 golang 数据类型就为 int64,否则为 uint64,如果 strict 为 false,则不关注 unsigned 修饰

MySQL 类型映射关系(稳定版本)

MySQL 类型 是否为 null 约束 Golang 类型
bitNObyte
tinyintNOuint64
tinyintYESsql.NullInt64
smallintNOuint64
smallintYESsql.NullInt64
mediumintNOuint64
mediumintYESsql.NullInt64
intNOuint64
intYESsql.NullInt64
middleintNOuint64
middleintYESsql.NullInt64
int1NOuint64
int1YESsql.NullInt64
int2NOuint64
int2YESsql.NullInt64
int3NOuint64
int3YESsql.NullInt64
int4NOuint64
int4YESsql.NullInt64
int8NOiunt64
int8YESsql.NullInt64
integerNOuint64
integerYESsql.NullInt64
bigintNOuint64
bigintYESsql.NullInt64
floatNOfloat64
floatYESsql.NullFloat64
float4NOfloat64
float4YESsql.NullFloat64
float8NOfloat64
float8YESsql.NullFloat64
dateNOtime.Time
datetimeNOtime.Time
timstampNOtime.Time
timeNOstring
yearNOint64
charNOstring
varcharNOstring
nvarcharNOstring
ncharNOstring
characterNOstring
longvarcharNOstring
linestringNOstring
multilinestringNOstring
binaryNOstring
varbinaryNOstring
tinytextNOstring
textNOstring
mediumtextNOstring
longtextNOstring
enumNOstring
setNOstring
jsonNOstring
blobNOstring
longblobNOstring
mediumblobNOstring
tinyblobNOstring
boolNObool
blleanNObool

goctl model pg 指令

goctl model pg 指令用于从 PostgreSQL 数据库中生成 Go 语言代码。

$ goctl model pg --help
Generate postgresql model

Usage:
goctl model pg [flags]
goctl model pg [command]

Available Commands:
datasource Generate model from datasource

Flags:
-h, --help help for pg


Use "goctl model pg [command] --help" for more information about a command.

goctl model pg datasource 指令

$ goctl model pg datasource --help
Generate model from datasource

Usage:
goctl model pg datasource [flags]

Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --cache Generate code with cache [optional]
-d, --dir string The target dir
-h, --help help for datasource
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--idea For idea plugin [optional]
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
-s, --schema string The table schema (default "public")
--strict Generate model in strict mode
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
-t, --table string The table or table globbing patterns in the database
--url string The data source of database,like "postgres://root:password@127.0.0.1:5432/database?sslmode=disable"
参数字段 参数类型 是否必填 默认值 参数说明
branchstringNO空字符串远程模板所在 git 分支名称,仅当 remote 有值时使用
cachebooleanNOfalse是否生成带缓存的代码
dirstringNO当前工作目录代码输出目录
easybooleanNOfalse是否暴露集合名称变量
homestringNO${HOME}/.goctl本地模板文件目录
ideabooleanNOfalse是否为 idea 使用,终端请忽略此字段
remotestringNO空字符串远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值
strictbooleanNOfalse是否是严格模式,如果是严格模式下,会对 unsigned 修饰的字段转换为对应的数据类型,主要针对数值型,例如:如果数据库中列为 bigint 类型,如果为unsigned 修饰则对应的 golang 数据类型就为 int64,否则为 uint64,如果 strict 为 false,则不关注 unsigned 修饰
stylestringNOgozero输出文件和目录的命名风格格式化符号,详情见 文件风格
table[]stringYESnil需要生成代码的表
urlstringYES空字符串数据库连接,格式 postgres://{{username}}:{{password}}@{{host_port}}/{{db}}?sslmode=disable

PostgreSQL 类型映射关系

PostgreSQL 类型 Golang 类型
boolbool
_boolpq.BoolArray
booleanbool
tinyintint64
smallintint64
mediumintint64
intint64
int1int64
int2int64
_int2pq.Int64Array
int3int64
int4int64
_int4pq.Int64Array
int8int64
_int8pq.Int64Array
integerint64
_integerpq.Int64Array
bigintint64
floatfloat64
float4float64
_float4pq.Float64Array
float8float64
_float8pq.Float64Array
doublefloat64
decimalfloat64
decfloat64
fixedfloat64
realfloat64
bitbyte
datetime.Time
datetimetime.Time
timestamptime.Time
timestring
yearint64
linestringstring
multilinestringstring
nvarcharstring
ncharstring
charstring
_charpq.StringArray
characterstring
varcharstring
_varcharpq.StringArray
binarystring
byteastring
longvarbinarystring
varbinarystring
tinytextstring
textstring
_textpq.StringArray
mediumtextstring
longtextstring
enumstring
setstring
jsonstring
jsonbstring
blobstring
longblobstring
mediumblobstring
tinyblobstring
ltree[]byte

类型映射自定义

类型映射自定义只有试验版本才能使用,关于如何开启试验版本,请参考 goctl env,关于配置使用请参考 goctl config

示例 1. 修改 decimal 为 decimal.Decimal 类型

  1. 在需要生成 model 的工程中初始化配置
$ goctl config init
goctl.yaml generated in ~/workspace/go-zero/tools/goctl/goctl.yaml
  1. 修改类型映射关系

灰色底纹部分为自定义映射类型。

model:
types_map:
bigint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
dec:
null_type: sql.NullFloat64
type: float64
decimal:
null_type: decimal.NullDecimal
pkg: github.com/shopspring/decimal
type: decimal.Decimal
...

添加 goctl 内置不支持的类型映射

我们在表中有一个 pg 的数据类型为 inet

-- auto-generated definition
create table student
(
id integer not null
constraint student_pk
primary key,
name varchar default ''::character varying not null,
age integer default 0 not null,
description integer not null,
ip_address inet default '0.0.0.0'::inet not null
);

alter table student
owner to postgres;

目前 goctl 内置类型映射不支持的类型,因此 goctl 会报错如下:

$ goctl model pg datasource --url="postgres://postgres:postgrespw@127.0.0.1:55000/postgres?sslmode=disable" --table="user,student" --dir . 
Error: unsupported database type: inet

要解决如上问题,在以往 goctl 版本是不支持的,只能给内置类型映射规则添加规则,然后再发版本,但是现在只需要在配置文件中添加一条类型映射规则皆可。

前提要 goctl 版本大于等于 1.6.5,且开始实验性功能

  1. 查看 goctl 版本是否满足条件
$ goctl env
GOCTL_OS=darwin
GOCTL_ARCH=arm64
GOCTL_HOME=/Users/sh00414ml/.goctl
GOCTL_DEBUG=False
GOCTL_CACHE=/Users/sh00414ml/.goctl/cache
GOCTL_EXPERIMENTAL=on # 实验性功能管开如果为 off 则需要开启,开启命令为 goctl env -w GOCTL_EXPERIMENTAL=on
GOCTL_VERSION=1.6.5 # goctl 版本
PROTOC_VERSION=3.19.4
PROTOC_GEN_GO_VERSION=v1.28.0
PROTO_GEN_GO_GRPC_VERSION=1.2.0
  1. 在目标工程项目中初始化 goctl 配置
$ goctl config
goctl.yaml generated in ~/demo/goctl-config/goctl.yaml # 这里以自己电脑输出准,这里仅供参考
  1. 修改 goctl.yaml

增加目标数据类型及映射关系,这里添加一个 inet 的映射,示例如下灰色底纹部分

model:
types_map:
bigint:
null_type: sql.NullInt64
type: int64
unsigned_type: uint64
...
inet:
null_type: sql.NullString
type: string
  1. 再次生成 model 代码
goctl model pg datasource --url="postgres://postgres:postgrespw@127.0.0.1:55000/postgres?sslmode=disable" --table="user,student" --dir . 
Done.