go-kit Truss 代码生成
go-kit Truss 代码生成
依赖
-
golang > 1.14
前提
Truss 安装
请参考: MacOS go-kit 自动生成代码工具 truss 安装
ProtoBuf 规范基本说明
请参考: go-kit Truss Protobuf 3 语法基本规范
Truss 使用
1. 创建项目
举个例子:
mkdir -p ~/goWork/truss_demo
2. 定义 protobuf
例如:vim ~/goWork/truss_demo/demo.proto
syntax = "proto3";
package demo;
import "github.com/metaverse/truss/deftree/googlethirdparty/annotations.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
service MyDemo {
// 获取
rpc GetSomething (DefaultRequest) returns (DefaultResponse) {
option (google.api.http) = {
get: "/my_demo_service/something"
additional_bindings {
get: "/my_demo_service/something"
}
};
}
// 提交
rpc PostSomething (PostSomethingRequest) returns (DefaultResponse) {
option (google.api.http) = {
custom {
kind: "HEAD"
path: "/my_demo_service/something"
}
additional_bindings {
post: "/my_demo_service/something"
body: "*"
}
};
}
}
message DefaultRequest {
string query = 1;
string fields = 2;
string order = 3;
string sortby = 4;
int64 limit = 5;
int64 offset = 6;
}
message PostSomethingRequest {
string id = 1;
string name = 2;
string age = 3;
}
message DefaultResponse {
string message = 1;
int64 code = 2;
google.protobuf.Struct data = 3;
}
3. 初始化 go mod
go mod init my_demo
如图:
mod初始化.png4. 生成代码
cd ~/goWork/truss_demo
truss ./demo.proto
执行完成后,会自动生成以下内容:
appledeMacBook-Pro:truss_demo apple$ truss ./demo.proto
appledeMacBook-Pro:truss_demo apple$ ls
demo.pb.go demo.proto go.mod mydemo-service
appledeMacBook-Pro:truss_demo apple$
如图:
truss代码生成.png结构图:
truss文件结构.png结构说明
truss_demo
|
|--demo.proto // protobuf 文件
|--demo.pb.go // RPC接口以及数据结构定义--自动生成
|--mydemo-service
|
|--cmd
| |
| |--mydemo
| |- main.go // 入口 - 自动生成,除特殊情况不建议修改
|
|--handlers //业务逻辑--需要我们写代码的地方
| |
| |--handlers.go //实际业务逻辑
| |--hooks.go // 配置信息以及阻断处理
| |--middlewares.go //中间件
|
|--svc // 通讯协议以及客户端,自动生成,除特殊情况不建议修改
| |
| |--client // 客户端定义
| | |
| | |--grpc
| | | |--client.go
| | |--http
| | |--client.go
| |--server // 服务端定义
| | |--run.go
| |
| |-- config.go // 服务端口定义
| |-- endpoints.go //接口定义
| |-- transport_grpc.go // grpc 传输协议层
| |-- transport_http.go // http 传输协议层
4. 导入包
最后记得使用 go mod
导入依赖。
go mod tidy
如图:
mod_tidy.png
5. 运行
go run mydemo-service/cmd/mydemo/main.go
如图:
go_run.png
6. 打包编译
最终项目发布时需要打包为 Linux 可执行程序。
如下所示:
cd ~/goWork/truss_demo && \
mkdir -p build && \
GOARCH=amd64 CGO_ENABLED=0 GOOS=linux go build -o build/main mydemo-service/cmd/mydemo/main.go
最后会在当前目录创建 build
文件夹,同时在 build
文件夹下生成 main
程序。
启动 mian
程序: ./main
即可。
7. 访问测试
不指定端口情况下默认端口分别为:
http: 5050
rpc: 5040
debug: 5060
因为没有写业务逻辑,返回值为默认值:
postman 测试:
postman_test.png
curl 测试:
curl --location --request GET 'localhost:5050/my_demo_service/something' -w "\n"
结果如图:
curl_test.png
特殊情况
数据结构不确定
对于上面 protobuf 定义时,有一种特殊情况需要注意:请求数据结构不确定。
我遇到的情况是:
因为业务需求,需要我提供一个回调接口,用来接收三方程序执行过程信息,但是并不知道具体数据结构,在咨询过truss
的开发人员后得知,这种情况需要特殊处理。
这时需要将 OPTION
和 POST
分开处理:
重新编辑 demo.proto
vim ~/demo.proto
编辑后:
syntax = "proto3";
package demo;
import "github.com/metaverse/truss/deftree/googlethirdparty/annotations.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
service MyDemo {
// 获取
rpc GetSomething (DefaultRequest) returns (DefaultResponse) {
option (google.api.http) = {
get: "/my_demo_service/something"
additional_bindings {
get: "/my_demo_service/something"
}
};
}
// 提交
rpc PostSomething (PostSomethingRequest) returns (DefaultResponse) {
option (google.api.http) = {
custom {
kind: "HEAD"
path: "/my_demo_service/something"
}
additional_bindings {
post: "/my_demo_service/something"
body: "*"
}
};
}
// 特殊请求
rpc SpecialPost (SpecialPostRequest) returns (DefaultResponse) {
option (google.api.http) = {
post: "/my_demo_service/special/{id}"
body : "*"
};
}
// 特殊请求
rpc SpecialPostHEAD (Empty) returns (Empty) {
option (google.api.http) = {
custom {
kind: "HEAD"
path: "/my_demo_service/special/*"
}
};
}
}
message Empty {}
message DefaultRequest {
string query = 1;
string fields = 2;
string order = 3;
string sortby = 4;
int64 limit = 5;
int64 offset = 6;
}
message PostSomethingRequest {
string id = 1;
string name = 2;
string age = 3;
}
message SpecialPostRequest {
string id = 1;
google.protobuf.Any metadata = 2;
}
message DefaultResponse {
string message = 1;
int64 code = 2;
google.protobuf.Struct data = 3;
}
重新生成代码
经过调整后 protobuf 文件发生变化,这时重新执行生成代码命令即可。
truss ./demo.proto
成功时返回:
appledeMacBook-Pro:truss_demo apple$ truss ./demo.proto
INFO[0000] Generating handler from rpc definition Method=SpecialPost
INFO[0000] Generating handler from rpc definition Method=SpecialPostHEAD
如图:
truss代码重生成.png注意:重生成代码时,如果
方法名称
发生变化,会导致业务逻辑代码被删除
。例如: 上例中
PostSomething
改为PostSomethings
, 会导致原有与PostSomething
相关内容被删除,之后新创建PostSomethings
相关方法。
其他
关于protobuf
中 message
定义特殊数据,protobuf
并不支持 golang
中的 interface
类型,具体如何接收/解析不确定
数据将在下篇文章中介绍,上面其实也有提及,感兴趣的朋友可以先提前去看一下 google/protobuf/any.proto
以及 google/protobuf/structs.proto
.
这次先介绍到这里,如有错误,欢迎留言指正。