快速开始
proto3 语法
概述
Protocol buffers 是 Google 的语言中立、平台中立、可扩展的结构化数据序列化机制——像 XML,但更小、更快、更简单。 您定义了一次数据的结构化方式,然后您可以使用特殊生成的源代码轻松地将结构化数据写入各种数据流并使用各种语言从中读取结构化数据。
tips: 所有项目采用proto3语法
快速入门
简单的示例
// 声明 proto 语法版本,固定值
syntax = "proto3";
// proto 包名
package greet;
// 生成 golang 代码后的包名
option go_package = "gitlab.galaxy-immi.com/Backend-group/proto/pb/goods/greet";
// 定义结构体, 请求消息以 Request 结尾
message HelloRequest{
string message = 1;
}
// 定义结构体, 应答消息以 Response 结尾
message HelloResponse{
int32 status = 1;
}
// 定义 Greet 服务
service Greet {
rpc Hello(HelloRequest) returns (HelloResponse);
}
创建项目
autocode创建项目
autocode init 项目名
目录结构
├─boot 引导文件, 初始化
├─domain 领域
│ ├─entity 实体层, ent schema 层
│ ├─repository repository层, 数据库的CURD层
│ └─service service 层
├─infra 基础设施层
│ └─db db 连接以及连接池配置
HTTP开发
框架集成了 gRPC-Gateway
, 因此我们只需要在定义 rpc
的时候附带加上 http
的定义即可。
如果项目不需要提供 HTTP
接口,那么只需要编辑 proto
文件, 将 google.api.http
选项清空即可,如果你需要提供 HTTP
接口,只需要编辑
google.api.http
选项即可,如:
- GET 请求
// 需要引入proto
import "google/api/annotations.proto";
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse) {
option(google.api.http) = { // 定义
get: "/hello",
};
}
}
- POST 请求
// 需要引入proto
import "google/api/annotations.proto";
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse) {
option(google.api.http) = { // 定义
post: "/hello" // HTTP请求方法是 POST, 路由是 /hello
body: "*" // 将整个http请求的body映射到HelloRequest结构体,如果需要指定字段,那么此处填写字段名
};
}
}
- POST 请求指定字段
// 需要引入proto
import "google/api/annotations.proto";
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse) {
option(google.api.http) = { // 定义
post: "/hello" // HTTP请求方法是 POST, 路由是 /hello
body: "items" // 将整个http请求的body映射到HelloRequest结构体的items字段
};
}
}
- PUT DELETE 等等一样
// 需要引入proto
import "google/api/annotations.proto";
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse) {
option(google.api.http) = { // 定义
delete: "/hello" // HTTP请求方法是 DELETE, 路由是 /hello
};
}
}
// 需要引入proto
import "google/api/annotations.proto";
service Hello {
rpc Hello(HelloRequest) returns (HelloResponse) {
option(google.api.http) = { // 定义
put: "/hello" // HTTP请求方法是 PUT, 路由是 /hello
body: "*"
};
}
}
如果你是需要按照 数据库 & 表
生成对应的增删改查五个方法的 proto
文件,可以使用 autocode
按如下步骤操作即可:
需要先切到 proto
项目,然后执行如下命令:
linux & mac下通配符 *
需要使用 \*
替代
autocode curd 数据库 表 --out=src下的目录/xxx_rpc.proto
--out=路径填写 不包含src文件夹
然后可以在对应的目录下看到新生成的文件以及对应的增删改查五个方法,以 cuser-server库的yh_apps为例:
PS D:\proto> autocode curd cuser-server yh_apps --out=cuser/cuser_rpc.proto
就可以在目录看到新生成的 yh_apps.go
文件以及在cuser_rpc.proto新生成的五个方法:
+ rpc ListYhApps ( cuserpb.ListYhAppsRequest ) returns ( cuserpb.ListYhAppsResponse ) {
+ option (google.api.http) = { get: "/cuser/yh-apps/list" };
+ }
+
+ rpc DelYhApps ( cuserpb.DelYhAppsRequest ) returns ( cuserpb.DelYhAppsResponse ) {
+ option (google.api.http) = { delete: "/cuser/yh-apps/del", body: "*" };
+ }
+
+ rpc AddYhApps ( cuserpb.AddYhAppsRequest ) returns ( cuserpb.AddYhAppsResponse ) {
+ option (google.api.http) = { post: "/cuser/yh-apps/add", body: "*" };
+ }
+
+ rpc EditYhApps ( cuserpb.EditYhAppsRequest ) returns ( cuserpb.EditYhAppsResponse ) {
+ option (google.api.http) = { put: "/cuser/yh-apps/edit", body: "*" };
+ }
+
+ rpc DetailYhApps ( cuserpb.DetailYhAppsRequest ) returns ( cuserpb.DetailYhAppsResponse ) {
+ option (google.api.http) = { get: "/cuser/yh-apps/detail" };
+ }
然后就可以在 service
层编写逻辑代码即可。
gRPC开发
常规的 gRPC
开发模式只需要定义 rpc
方法. 以及所需的 message
定义.
message HelloRequest {
int32 id = 1; // 数据ID
}
message HelloResponse {
string message = 1; // 消息
}
service Hello {
// 测试方法
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
proto 文件编译
通常情况下我们需要安装 protoc
编译器,以及对应的 go插件
来翻译成对应的 go代码
,这里涉及到多个版本问题。为了解决这一问题。我们 autocode
工具将protoc以及其他的插件进行了整合。
使用方式如下:
执行命令前需要切到proto/src目录下:
PS D:\projects\yh\proto\src> autocode proto after\*.proto
New config client
libprotoc 24.4
protoc-gen-app.exe have been installed.
protoc-gen-go.exe have been installed.
protoc-gen-validate.exe have been installed.
protoc-gen-grpc-gateway.exe have been installed.
protoc-gen-openapiv2.exe have been installed.
protoc-gen-go-grpc.exe have been installed.
current pwd: D:\projects\yh\proto\src
Inject tags directory: ..\pb
2024-08-21T20:16:29.163+0800 INFO called on nil broadcaster
inject tags success
这里不需要电脑安装 protoc
以及对应的插件, 如果没有对应的插件, autocode
会自动安装对应的与之匹配的版本。
数据库操作
我们框架采用 Facebook开源的 ent
框架, 框架特点如下:
ent是一个简单但功能强大的 Go 实体框架,它可以轻松构建和维护具有大型数据模型的应用程序,并遵循以下原则:
- 轻松将数据库模式建模为图形结构。
- 将模式定义为编程 Go 代码。
- 基于代码生成的静态类型。
- 数据库查询和图形遍历很容易编写。
- 使用 Go 模板可以轻松扩展和定制。
因为 ent
框架需要我们编写对应的表的 schema
文件,为了提速开发,脚手架支持针对于数据库和表自动生成 schema
文件, 具体的步骤如下:
命令行需要先切到到项目文件夹
linux & mac下通配符 *
需要使用 \*
替代
PS D:\hello-server> autocode ent 数据库 表
以 cuser-server 库 yh_apps 表为例
PS D:\hello-server> autocode ent cuser-server yh_apps
New config client
识别到项目为: hello-server
可选数据库:new_diy cuser-server crm galaxy-crm marketing-server auth_server ServerSiteMicros FlowMicros infoflow-server UserMicros rpc PresaleMicros smart-writing goods-server article_server kidsbay-server galaxy-sop superapp-server MemberMicros activity-server cron galaxy
表名: yh_apps
看到最后输出了表名,证明操作成功了,由于历史原因,我们的domain/entity目录下的子目录不是很规范,所以ent
子命令支持 --entity 指定。
PS D:\hello-server> autocode ent cuser-server yh_apps --entity=cuser
New config client
识别到项目为: hello-server
可选数据库:new_diy cuser-server crm galaxy-crm marketing-server auth_server ServerSiteMicros FlowMicros infoflow-server UserMicros rpc PresaleMicros smart-writing goods-server article_server kidsbay-server galaxy-sop superapp-server MemberMicros activity-server cron galaxy
表名: yh_apps
对于 ent schema 文件,我们需要使用 ent generate 去完成代码的生成,我们的脚手架也支持生成 采用 autocode generate
.
PS D:\hello-server> autocode generate .\domain\entity\cuserserver\schema\
New config client
ent.exe have been installed
2024-08-21T20:03:51.238+0800 INFO called on nil broadcaste
命令执行完毕会基于 schema
生成对应的增删改查的代码.
生成的目录结构如下:
├─boot
├─domain
│ ├─entity
│ │ └─cuserserver
│ │ ├─enttest
│ │ ├─hook
│ │ ├─migrate
│ │ ├─predicate
│ │ ├─runtime
│ │ ├─schema
│ │ └─yhapps
│ ├─repository
│ └─service
├─http
├─infra
│ └─db
日志
我们项目里面采用了 uber
开发的 zap
日志库作为载体,代码中碰到需要进行打日志的地方,可以使用快捷方式进行日志打印:
log.Info(`hello world`)
log.Warn(`hello world`)
log.Error(`hello world`)
或者
log.Sugar().Warn()
log.Sugar().Info()
log.Sugar().Error()
等等
框架会统一输出 json
格式的日志文件进行落地.