restore: re-add sanitized go-zero/goctl.md after path-history rewrite
git-filter-repo --invert-paths removed note/资源/编程/Golang/go-zero/goctl.md from all history in this isolated clone. This commit re-adds only the sanitized file so the final tree matches merge candidate 58ba5eb7676480211dc6a4c2d8f3a08402d8a080.
This commit is contained in:
@@ -0,0 +1,156 @@
|
|||||||
|
## API
|
||||||
|
|
||||||
|
### goctl代码生成
|
||||||
|
|
||||||
|
可以在doc/genCode.md查看
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 生成多个types类型的话需要关闭这个实验性功能
|
||||||
|
goctl env -w GOCTL_EXPERIMENTAL=off
|
||||||
|
|
||||||
|
# 代码生成,会自动处理引入的子api文件
|
||||||
|
goctl api go -api background.api -dir . --home D:/zhangyuxin/template/1.8.3
|
||||||
|
goctl api go -api login.api -dir . --home ../../../deploy/goctl
|
||||||
|
goctl api go -api main.api -dir . --home ../../deploy/goctl
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数校验
|
||||||
|
|
||||||
|
| 接收规则 | 说明 | 示例 |
|
||||||
|
| -------- | ------------------------------------------ | ------------------------------- |
|
||||||
|
| optional | 当前字段是可选参数,允许为零值(zero value) | `json:"foo,optional"` |
|
||||||
|
| options | 当前参数仅可接收的枚举值 | `json:"gender,options=foo|bar"` |
|
||||||
|
| default | 当前参数默认值 | `json:"gender,default=male"` |
|
||||||
|
| range | 当前参数数值有效范围,支持开/闭区间 | `json:"age,range=[0:120]"` |
|
||||||
|
|
||||||
|
#### **`optional`** **与** **`omitempty`** **的区别**
|
||||||
|
|
||||||
|
两者都写在 json/form tag 的 options 里,但作用域完全不同,不可互相替代
|
||||||
|
|
||||||
|
##### `optional` —— goctl 专用,控制 Swagger 与请求校验
|
||||||
|
|
||||||
|
- **Swagger 生成**:标了 `optional` 的字段不进 `required` 数组,Apifox/Swagger UI 显示为可选;未标的字段进 `required` 数组,显示为必填
|
||||||
|
- **请求校验**:goctl 生成的 logic 不会对标了 `optional` 的字段做必填校验
|
||||||
|
- **判定逻辑**:goctl 遍历 tag options,找到 `optional` 关键字即判定为可选
|
||||||
|
|
||||||
|
##### `omitempty` —— Go 标准库指令,控制 JSON 序列化
|
||||||
|
|
||||||
|
- **JSON 序列化**:字段为零值(0、""、nil、false)时,响应 JSON 中**不输出**该字段
|
||||||
|
- **Swagger 生成**:**goctl 完全不识别**,字段仍按未标 `optional` 处理,即判定为 required
|
||||||
|
- **请求校验**:无影响
|
||||||
|
|
||||||
|
## RPC
|
||||||
|
|
||||||
|
### goctl代码生成
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 主proto文件代码生成
|
||||||
|
goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=. --proto_path=. -m --home ../../../deploy/goctl
|
||||||
|
|
||||||
|
# 主proto文件中引入的proto代码生成
|
||||||
|
protoc.exe -I ./ --go_out=. --go-grpc_out=. ./user_model.proto
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
当`proto`文件里面定义了多个 service的时候,需要额外注意,还要再main函数中手动注册一下
|
||||||
|
|
||||||
|
> 每个 proto 文件应该聚焦于一个核心概念/实体。一个文件里定义太多 service 通常是设计需要重新考虑的信号
|
||||||
|
|
||||||
|
注册示例
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
ebookServer "olive/services/product/rpc/internal/server/ebookservice"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configFile = flag.String("f", "etc/product.yaml", "the config file")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var c config.Config
|
||||||
|
conf.MustLoad(*configFile, &c)
|
||||||
|
ctx := svc.NewServiceContext(c)
|
||||||
|
|
||||||
|
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||||
|
// 新服务
|
||||||
|
productrpcmodel.RegisterEbookServiceServer(grpcServer, ebookServer.NewEbookServiceServer(ctx))
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
fmt.Printf("Starting product RPC server at %s...\n", c.ListenOn)
|
||||||
|
s.Start()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### proto代码生成错误:File not found错误
|
||||||
|
|
||||||
|
- 错误描述
|
||||||
|
|
||||||
|
执行 protoc 报 google/protobuf/timestamp.proto: File not found. 的错提示File not found
|
||||||
|
|
||||||
|
- 解决方式
|
||||||
|
|
||||||
|
重新下载[protoc](https://github.com/protocolbuffers/protobuf/releases),解压后,将整个include目录复制到protoc执行文件同一级目录下
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## model
|
||||||
|
|
||||||
|
可以在doc/genCode.md查看
|
||||||
|
|
||||||
|
**Model 层**:只做 **“业务循环”** + **“SQL 查询”** + **“结果封装”**,不关心字符串到时间的转换和 Protobuf 类型。
|
||||||
|
|
||||||
|
### goctl代码生成
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# mysql根据远程数据库表生成
|
||||||
|
goctl model mysql datasource --url="user:password@tcp(127.0.0.1:3306)/database" --table="user_table" --dir="." -c --home D:/template/1.8.3
|
||||||
|
|
||||||
|
# mysql根据ddl生成
|
||||||
|
goctl model mysql ddl --src h5.sql --dir . -c --home D:/template/1.8.3
|
||||||
|
|
||||||
|
# pgsql根据远程数据库表生成
|
||||||
|
goctl model pg datasource -url "postgres://user:password@127.0.0.1:15432/database" -table user -dir ./user --cache --home D:/template/1.8.3
|
||||||
|
|
||||||
|
# pgsql根据远程数据库表生成,带模式(schema)
|
||||||
|
goctl model pg datasource -url "postgres://user:password@127.0.0.1:25432/database?sslmode=disable" -s "users" -table "profile" -dir ./go-zero/model/users/ --cache --home ../../deploy/goctl
|
||||||
|
```
|
||||||
|
|
||||||
|
> 有的时候会遇到`unsupported database type`的错误,如果需要支持该字段,需要在`goctl.yaml`文件添加数据库类型映射配置,并保证goctl环境变量`GOCTL_EXPERIMENTAL=on`开启。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## config
|
||||||
|
|
||||||
|
`goctl config`是用于对goctl静态配置文件做管理。
|
||||||
|
|
||||||
|
```
|
||||||
|
$ goctl config --help
|
||||||
|
Usage:
|
||||||
|
goctl config [command]
|
||||||
|
|
||||||
|
Available Commands:
|
||||||
|
clean Clean goctl config file
|
||||||
|
init Initialize goctl config file
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-h, --help help for config
|
||||||
|
|
||||||
|
|
||||||
|
Use "goctl config [command] --help" for more information about a command.
|
||||||
|
```
|
||||||
|
|
||||||
|
`goctl.yaml`文件字段
|
||||||
|
|
||||||
|
目前暂时仅支持对 model 数据类型映射的配置
|
||||||
|
|
||||||
|
| 字段名称 | 说明 |
|
||||||
|
| --------------- | ------------------------------------------------------------ |
|
||||||
|
| model | model 配置 |
|
||||||
|
| model.types_map | model 配置之类型映射规则,是一个 map<string,obj> 结构,key 为数据库类型,value 为映射对象 |
|
||||||
|
|
||||||
Reference in New Issue
Block a user