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
参数字段 | 参数类型 | 是否必填 | 默认值 | 参数说明 |
---|---|---|---|---|
branch | string | NO | 空字符串 | 远程模板所在 git 分支名称,仅当 remote 有值时使用 |
cache | boolean | NO | false | 是否生成带缓存的代码 |
dir | string | NO | 当前工作目录 | 代码输出目录 |
easy | boolean | NO | false | 是否暴露集合名称变量 |
home | string | NO | ${HOME}/.goctl | 本地模板文件目录 |
remote | string | NO | 空字符串 | 远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值 |
style | string | NO | gozero | 输出文件和目录的命名风格格式化符号,详情见文件风格 |
type | []string | YES | nil | 结构体类型名称 |
使用示例
以下我们以生成一个 User 结构体为例。
- 生成带缓存的代码
# 进入用户 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
查看代码
- error.go
- usermodel.go
- usermodelgen.go
- usertypes.go
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/monc"
)
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
}
customUserModel struct {
*defaultUserModel
}
)
// NewUserModel returns a model for the mongo.
func NewUserModel(url, db, collection string, c cache.CacheConf) UserModel {
conn := monc.MustNewModel(url, db, collection, c)
return &customUserModel{
defaultUserModel: newDefaultUserModel(conn),
}
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
"context"
"time"
"github.com/zeromicro/go-zero/core/stores/monc"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var prefixUserCacheKey = "cache:user:"
type userModel interface {
Insert(ctx context.Context, data *User) error
FindOne(ctx context.Context, id string) (*User, error)
Update(ctx context.Context, data *User) error
Delete(ctx context.Context, id string) error
}
type defaultUserModel struct {
conn *monc.Model
}
func newDefaultUserModel(conn *monc.Model) *defaultUserModel {
return &defaultUserModel{conn: conn}
}
func (m *defaultUserModel) Insert(ctx context.Context, data *User) error {
if data.ID.IsZero() {
data.ID = primitive.NewObjectID()
data.CreateAt = time.Now()
data.UpdateAt = time.Now()
}
key := prefixUserCacheKey + data.ID.Hex()
_, err := m.conn.InsertOne(ctx, key, data)
return err
}
func (m *defaultUserModel) FindOne(ctx context.Context, id string) (*User, error) {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, ErrInvalidObjectId
}
var data User
key := prefixUserCacheKey + id
err = m.conn.FindOne(ctx, key, &data, bson.M{"_id": oid})
switch err {
case nil:
return &data, nil
case monc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) Update(ctx context.Context, data *User) error {
data.UpdateAt = time.Now()
key := prefixUserCacheKey + data.ID.Hex()
_, err := m.conn.ReplaceOne(ctx, key, bson.M{"_id": data.ID}, data)
return err
}
func (m *defaultUserModel) Delete(ctx context.Context, id string) error {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return ErrInvalidObjectId
}
key := prefixUserCacheKey + id
_, err = m.conn.DeleteOne(ctx, key, bson.M{"_id": oid})
return err
}
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
// TODO: Fill your own fields
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
}
- 生成不带缓存的代码
# 进入用户 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
查看代码
- error.go
- usermodel.go
- usermodelgen.go
- usertypes.go
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import "github.com/zeromicro/go-zero/core/stores/mon"
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
}
customUserModel struct {
*defaultUserModel
}
)
// NewUserModel returns a model for the mongo.
func NewUserModel(url, db, collection string) UserModel {
conn := mon.MustNewModel(url, db, collection)
return &customUserModel{
defaultUserModel: newDefaultUserModel(conn),
}
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
"context"
"time"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type userModel interface {
Insert(ctx context.Context, data *User) error
FindOne(ctx context.Context, id string) (*User, error)
Update(ctx context.Context, data *User) error
Delete(ctx context.Context, id string) error
}
type defaultUserModel struct {
conn *mon.Model
}
func newDefaultUserModel(conn *mon.Model) *defaultUserModel {
return &defaultUserModel{conn: conn}
}
func (m *defaultUserModel) Insert(ctx context.Context, data *User) error {
if data.ID.IsZero() {
data.ID = primitive.NewObjectID()
data.CreateAt = time.Now()
data.UpdateAt = time.Now()
}
_, err := m.conn.InsertOne(ctx, data)
return err
}
func (m *defaultUserModel) FindOne(ctx context.Context, id string) (*User, error) {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, ErrInvalidObjectId
}
var data User
err = m.conn.FindOne(ctx, &data, bson.M{"_id": oid})
switch err {
case nil:
return &data, nil
case mon.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) Update(ctx context.Context, data *User) error {
data.UpdateAt = time.Now()
_, err := m.conn.ReplaceOne(ctx, bson.M{"_id": data.ID}, data)
return err
}
func (m *defaultUserModel) Delete(ctx context.Context, id string) error {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return ErrInvalidObjectId
}
_, err = m.conn.DeleteOne(ctx, bson.M{"_id": oid})
return err
}
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
// TODO: Fill your own fields
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
}
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
参数字段 | 参数类型 | 是否必填 | 默认值 | 参数说明 |
---|---|---|---|---|
branch | string | NO | 空字符串 | 远程模板所在 git 分支名称,仅当 remote 有值时使用 |
cache | boolean | NO | false | 是否生成带缓存的代码 |
dir | string | NO | 当前工作目录 | 代码输出目录 |
easy | boolean | NO | false | 是否暴露集合名称变量 |
home | string | NO | ${HOME}/.goctl | 本地模板文件目录 |
remote | string | NO | 空字符串 | 远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值 |
style | string | NO | gozero | 输出文件和目录的命名风格格式化符号,详情见文件风格 |
table | []string | YES | nil | 需要生成代码的表 |
url | string | YES | 空字符串 | 数据库连接,格式{{username}}:{{password}}@tcp({{host_port}})/{{db}} |
ignore-columns | []string | NO | nil | 需要忽略的字段,插入或者更新时需要忽略的字段,如 create_time |
strict | boolean | NO | false | 是否是严格模式,如果是严格模式下,会对 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
参数字段 | 参数类型 | 是否必填 | 默认值 | 参数说明 |
---|---|---|---|---|
branch | string | NO | 空字符串 | 远程模板所在 git 分支名称,仅当 remote 有值时使用 |
cache | boolean | NO | false | 是否生成带缓存的代码 |
dir | string | NO | 当前工作目录 | 代码输出目录 |
easy | boolean | NO | false | 是否暴露集合名称变量 |
home | string | NO | ${HOME}/.goctl | 本地模板文件目录 |
remote | string | NO | 空字符串 | 远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值 |
src | string | YES | 空字符串 | sql 文件路径 |
style | string | NO | gozero | 输出文件和目录的命名风格格式化符号,详情见文件风格 |
ignore-columns | []string | NO | nil | 需要忽略的字段,插入或者更新时需要忽略的字段,如 create_time |
strict | boolean | NO | false | 是否是严格模式,如果是严格模式下,会对 unsigned 修饰的字段转换为对应的数据类型,主要针对数值型,例如:如果数据库中列为 bigint 类型,如果为unsigned 修饰则对应的 golang 数据类型就为 int64 ,否则为 uint64 ,如果 strict 为 false,则不关注 unsigned 修饰 |
MySQL 类型映射关系
- strict 为 true 时,且 unsigned 修饰
- strict 不为 true 时
MySQL 类型 | 是否为 null 约束 | Golang 类型 |
---|---|---|
bit | NO | byte |
tinyint | NO | uint64 |
tinyint | YES | sql.NullInt64 |
smallint | NO | uint64 |
smallint | YES | sql.NullInt64 |
mediumint | NO | uint64 |
mediumint | YES | sql.NullInt64 |
int | NO | uint64 |
int | YES | sql.NullInt64 |
middleint | NO | uint64 |
middleint | YES | sql.NullInt64 |
int1 | NO | uint64 |
int1 | YES | sql.NullInt64 |
int2 | NO | uint64 |
int2 | YES | sql.NullInt64 |
int3 | NO | uint64 |
int3 | YES | sql.NullInt64 |
int4 | NO | uint64 |
int4 | YES | sql.NullInt64 |
int8 | NO | iunt64 |
int8 | YES | sql.NullInt64 |
integer | NO | uint64 |
integer | YES | sql.NullInt64 |
bigint | NO | uint64 |
bigint | YES | sql.NullInt64 |
float | NO | float64 |
float | YES | sql.NullFloat64 |
float4 | NO | float64 |
float4 | YES | sql.NullFloat64 |
float8 | NO | float64 |
float8 | YES | sql.NullFloat64 |
date | NO | time.Time |
datetime | NO | time.Time |
timstamp | NO | time.Time |
time | NO | string |
year | NO | int64 |
char | NO | string |
varchar | NO | string |
nvarchar | NO | string |
nchar | NO | string |
character | NO | string |
longvarchar | NO | string |
linestring | NO | string |
multilinestring | NO | string |
binary | NO | string |
varbinary | NO | string |
tinytext | NO | string |
text | NO | string |
mediumtext | NO | string |
longtext | NO | string |
enum | NO | string |
set | NO | string |
json | NO | string |
blob | NO | string |
longblob | NO | string |
mediumblob | NO | string |
tinyblob | NO | string |
bool | NO | bool |
bllean | NO | bool |
MySQL 类型 | 是否为 null 约束 | Golang 类型 |
---|---|---|
bit | NO | byte |
tinyint | NO | int64 |
tinyint | YES | sql.NullInt64 |
smallint | NO | int64 |
smallint | YES | sql.NullInt64 |
mediumint | NO | int64 |
mediumint | YES | sql.NullInt64 |
int | NO | int64 |
int | YES | sql.NullInt64 |
middleint | NO | int64 |
middleint | YES | sql.NullInt64 |
int1 | NO | int64 |
int1 | YES | sql.NullInt64 |
int2 | NO | int64 |
int2 | YES | sql.NullInt64 |
int3 | NO | int64 |
int3 | YES | sql.NullInt64 |
int4 | NO | int64 |
int4 | YES | sql.NullInt64 |
int8 | NO | int64 |
int8 | YES | sql.NullInt64 |
integer | NO | int64 |
integer | YES | sql.NullInt64 |
bigint | NO | int64 |
bigint | YES | sql.NullInt64 |
float | NO | float64 |
float | YES | sql.NullFloat64 |
float4 | NO | float64 |
float4 | YES | sql.NullFloat64 |
float8 | NO | float64 |
float8 | YES | sql.NullFloat64 |
date | NO | time.Time |
datetime | NO | time.Time |
timstamp | NO | time.Time |
time | NO | string |
year | NO | int64 |
char | NO | string |
varchar | NO | string |
nvarchar | NO | string |
nchar | NO | string |
character | NO | string |
longvarchar | NO | string |
linestring | NO | string |
multilinestring | NO | string |
binary | NO | string |
varbinary | NO | string |
tinytext | NO | string |
text | NO | string |
mediumtext | NO | string |
longtext | NO | string |
enum | NO | string |
set | NO | string |
json | NO | string |
blob | NO | string |
longblob | NO | string |
mediumblob | NO | string |
tinyblob | NO | string |
bool | NO | bool |
bllean | NO | bool |
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"
参数字段 | 参数类型 | 是否必填 | 默认值 | 参数说明 |
---|---|---|---|---|
branch | string | NO | 空字符串 | 远程模板所在 git 分支名称,仅当 remote 有值时使用 |
cache | boolean | NO | false | 是否生成带缓存的代码 |
dir | string | NO | 当前工作目录 | 代码输出目录 |
easy | boolean | NO | false | 是否暴露集合名称变量 |
home | string | NO | ${HOME}/.goctl | 本地模板文件目录 |
idea | boolean | NO | false | 是否为 idea 使用,终端请忽略此字段 |
remote | string | NO | 空字符串 | 远程模板所在 git 仓库地址,当此字段传值时,优先级高于 home 字段值 |
strict | boolean | NO | false | 是否是严格模式,如果是严格模式下,会对 unsigned 修饰的字段转换为对应的数据类型,主要针对数值型,例如:如果数据库中列为 bigint 类型,如果为unsigned 修饰则对应的 golang 数据类型就为 int64 ,否则为 uint64 ,如果 strict 为 false,则不关注 unsigned 修饰 |
style | string | NO | gozero | 输出文件和目录的命名风格格式化符号,详情见文件风格 |
table | []string | YES | nil | 需要生成代码的表 |
url | string | YES | 空字符串 | 数据库连接,格式 postgres://{{username}}:{{password}}@{{host_port}}/{{db}}?sslmode=disable |
PostgreSQL 类型映射关系
PostgreSQL 类型 | Golang 类型 |
---|---|
bool | bool |
_bool | pq.BoolArray |
boolean | bool |
tinyint | int64 |
smallint | int64 |
mediumint | int64 |
int | int64 |
int1 | int64 |
int2 | int64 |
_int2 | pq.Int64Array |
int3 | int64 |
int4 | int64 |
_int4 | pq.Int64Array |
int8 | int64 |
_int8 | pq.Int64Array |
integer | int64 |
_integer | pq.Int64Array |
bigint | int64 |
float | float64 |
float4 | float64 |
_float4 | pq.Float64Array |
float8 | float64 |
_float8 | pq.Float64Array |
double | float64 |
decimal | float64 |
dec | float64 |
fixed | float64 |
real | float64 |
bit | byte |
date | time.Time |
datetime | time.Time |
timestamp | time.Time |
time | string |
year | int64 |
linestring | string |
multilinestring | string |
nvarchar | string |
nchar | string |
char | string |
_char | pq.StringArray |
character | string |
varchar | string |
_varchar | pq.StringArray |
binary | string |
bytea | string |
longvarbinary | string |
varbinary | string |
tinytext | string |
text | string |
_text | pq.StringArray |
mediumtext | string |
longtext | string |
enum | string |
set | string |
json | string |
jsonb | string |
blob | string |
longblob | string |
mediumblob | string |
tinyblob | string |
ltree | []byte |