您的位置:首页 > 房产 > 家装 > 深圳网站免费制作_成都自适应建站哪家好_旅游网络营销的渠道有哪些_西安百度公司

深圳网站免费制作_成都自适应建站哪家好_旅游网络营销的渠道有哪些_西安百度公司

2024/12/27 5:29:51 来源:https://blog.csdn.net/weixin_45565886/article/details/142282383  浏览:    关键词:深圳网站免费制作_成都自适应建站哪家好_旅游网络营销的渠道有哪些_西安百度公司
深圳网站免费制作_成都自适应建站哪家好_旅游网络营销的渠道有哪些_西安百度公司

tRPC多个proto文件、optional、import等用法【2 使用进阶】

多个proto文件场景

  • 项目代码(欢迎star⭐️) :
    Github:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-trpc/02-complicated

有时我们为了结构清晰,会使用多个proto文件。比如一个classroom里会有多个学生。

  • classroom.proto
  • student.proto

classroom.proto里肯定是需要使用student.proto,因此我们需要使用import关键字导入,然后trpc create分别生成classroom.trpc.go、student.trpc.go文件。

1 编写proto文件

项目结构:
在这里插入图片描述

student.proto

syntax = "proto3";package trpc.complicated;
option go_package="ziyi.com/go-demo/go-trpc/02-complicated/pb";message Student {string name = 1;int32 age = 2;
}

classroom.proto

虽然goland import报红,这是因为我们没有配置goland识别proto文件的路径。但并不影响执行trpc create命令生成trpc.go文件。

在这里插入图片描述
或者我们也可以在goland配置proto文件路径:
在这里插入图片描述

syntax = "proto3";package trpc.complicated;
option go_package="ziyi.com/go-demo/go-trpc/02-complicated/pb";import "student.proto"; // 导入外部proto文件(因为两个proto文件都在同一个目录,因此这里可使用相对路径)//定义教室服务
service ClassroomService {rpc GetInfo (Request) returns (Response) {}
}message Request {int32 roomId = 1;
}message Response {Classroom classroom = 1;
}//定义教室struct
message Classroom {int32 id = 1;string name = 2;string address = 3;repeated Student students = 4;
}

2 trpc create生成trpc.go文件

# 生成classroom.pb.go、classroom.trpc.go文件
trpc create -p classroom.proto \--rpconly \--nogomod \--mock=false \--protodir . \-o .# 生成student.pb.go文件
trpc create -p student.proto \--rpconly \--nogomod \--mock=false \--protodir . \-o .# 解释:
# -p student.proto 指定要生成代码的 .proto 文件
# --rpconly 只生成 stub 代码
# --nogomod 不生成 go.mod 文件
# --mock=false 禁用 mock 代码生成
# --protodir . 指定 .proto 文件的搜索路径
# -o . 输出目录为当前目录

在这里插入图片描述
生成后项目结构:
在这里插入图片描述

如果发现报错: generate files from template inside create rpc stub err: template execute err: template: trpc.go.tpl:91:31: executing “trpc.go.tpl” at <gofulltypex .RequestType $.FileDescriptor>: error calling gofulltypex: invalid type:xxx。

  • 观察是否是.proto文件未加package xxxx;

3 编写server端

trpc_go.yaml

配置服务名称、监听地址、端口

server:service:#       服务名称- name: trpc.classroom#      监听地址ip: 127.0.0.1#      服务监听端口port: 8088

server.go

对外暴露服务

package mainimport ("context""fmt""trpc.group/trpc-go/tnet/log""trpc.group/trpc-go/trpc-go""ziyi.com/02-complicated/pb"
)func main() {trpc.ServerConfigPath = "/Users/ziyi/GolandProjects/ziyifast-code_instruction/go-demo/go-trpc/02-complicated/server/trpc_go.yaml"server := trpc.NewServer()pb.RegisterClassroomServiceService(server, &ClassRoomService{})if err := server.Serve(); err != nil {panic(err)}
}type ClassRoomService struct {
}func (c *ClassRoomService) GetInfo(ctx context.Context, request *pb.Request) (*pb.Response, error) {log.Info("【server】receive ", request.RoomId, " info...")if request.RoomId != 1 {return nil, fmt.Errorf("the classroom does not exist")}rsp := new(pb.Response)room := &pb.Classroom{Name:    "grade7_21",Address: "北京市 朝阳区 大屯路 ",Students: []*pb.Student{&pb.Student{Name: "小明",Age:  18,},},}rsp.Classroom = roomreturn rsp, nil
}

4 编写client端

client.go

请求服务端

package mainimport ("context""trpc.group/trpc-go/trpc-go/client""ziyi.com/02-complicated/pb"
)func main() {cli := pb.NewClassroomServiceClientProxy(client.WithTarget("ip://localhost:8088"))rsp, err := cli.GetInfo(context.TODO(), &pb.Request{RoomId: 1})if err != nil {panic(err)}println("【client】 receive ", rsp.Classroom.Name)
}

5 演示

启动服务端、客户端,客户端向服务端发起请求查询id为1的classroom信息。

在这里插入图片描述

其他字段使用场景

具体代码地址:

  • https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-trpc/03-keyword

message:定义结构体struct

// message: 定义结构体,类比go中的type
message Request {// optional: 可选字段optional string reqCreateTime = 1;string name = 2;//tips:字段后的1、2、1001等id标识,不用连续,只要全局唯一即可。通常为了后续有字段扩展我们字段的id都会跳着定义。map<string, string> extInfo = 1001;}

service:定义服务

// service : 定义服务
service KeywordService {rpc GetKeyword(Request) returns (Response);//...
}

optional:可选字段

如果字段为optional,且未设置值,在序列化时候则不会包含该字段,且不会给字段默认值

// message: 定义结构体,类比go中的type
message Request {// optional: 可选字段optional string reqCreateTime = 1;map<string, string> reqInfo = 2;
}

repeated:可重复字段=>列表(切片)

message Classroom{string name = 1;//repeated 列表(切片)repeated int32 studentIds = 2;
}

enum:定义枚举类

enum ResponseCode {OK = 0;FAIL = 1;INVALID_PARAM = 2;
}

validate:规则校验

定义校验validate.proto:

使用:

// 案例一:
// 账号信息
message Account {AccountType type = 1; string id = 2 [(validate.rules).string.kstr = true]; // 账号id
}//案例二:
message Req {Account account        		  = 1; map<string, string> ext                 = 2; repeated string variable_ids            = 3[(validate.rules).repeated = {min_items: 0, max_items: 100, items: {string: {kstr: true, min_len: 1, max_len: 100}}}]; 
}

extend:扩展字段

例如下面代码实现了 对google.protobuf.MessageOptions 的扩展,用于在消息级别应用验证规则。具体来说:

  • disabled:如果设置为 true,则会禁用此消息的所有验证规则,包括其支持验证的所有字段的验证规则。
  • ignored:如果设置为 true,则会跳过为此消息生成验证方法。

validate.proto:

// Validation rules applied at the message level
extend google.protobuf.MessageOptions {// Disabled nullifies any validation rules for this message, including any// message fields associated with it that do support validation.optional bool disabled = 1071;// Ignore skips generation of validation methods for this message.optional bool ignored = 1072;	
}

oneof type:单选

oneof 关键字表示在 FieldRules 消息中只能选择其中一个字段。这意味着每个 FieldRules 实例只能定义一种类型的验证规则。例如,如果选择了 FloatRules,则其他字段(如 DoubleRules 或 StringRules)将不会生效。

// FieldRules encapsulates the rules for each type of field. Depending on the
// field, the correct set should be used to ensure proper validations.
message FieldRules {optional MessageRules message = 17;oneof type {// Scalar Field TypesFloatRules    float    = 1;DoubleRules   double   = 2;Int32Rules    int32    = 3;Int64Rules    int64    = 4;}
}

Validate使用场景:校验字段

tRPC 验证器(Validator)是一种用于在 tRPC 通信过程中进行数据验证的工具,通过在 .proto 文件中定义验证规则(例如长度限制、格式检查等),确保客户端和服务器之间传递的数据符合预期的格式和约束条件。

  • 我们这里采用开源的protoc-gen-validate自定义校验工具来讲解。

安装protoc-gen-validate工具

# fetches this repo into $GOPATH
go get github.com/envoyproxy/protoc-gen-validate

下载之后如果发现依然无法执行protoc-gen-validate命令,解决办法:下载源码,手动编译。

  1. 下载源码:go install github.com/envoyproxy/protoc-gen-validate@latest
  2. 进入源码所在目录(如果配置了GOPATH,会直接下载到GOPATH/pkg/mod/github.com/…目录下):
  • 我的GOPATH:/Users/ziyi/go
  • 我下载的源码路径:/Users/ziyi/go/pkg/mod/github.com/envoyproxy/protoc-gen-validate@v1.1.0
  1. cd 进入源码目录,手动编译: sudo go build -o protoc-gen-validate main.go
  2. 编译后的二进制添加可执行权限:sudo chmod +x protoc-gen-validate
  3. 将二进制拷贝到/usr/bin下(或其他目录,只要该目录配置了环境变量,能在任何地方执行即可)

protoc-gen-validate可支持校验类型

官网地址:https://gitcode.com/gh_mirrors/pr/protoc-gen-validate/overview?utm_source=csdn_github_accelerator&isLogin=1

在这里插入图片描述

实战一:使用Validate默认规则

  • 官方文档: trpc validate官方文档
  • 全部代码:
    Github:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-trpc/04-validate

项目结构:

.
├── client
│   └── client.go
├── proto
│   ├── user_trpc.pb.go
│   ├── user.pb.go
│   ├── user.pb.validate.go
│   ├── user.proto
│   └── validate.proto
└── server└── server.go

在这里插入图片描述

1 编写user.proto

syntax = "proto3";import "validate.proto";option go_package = ".;proto";service UserService {rpc GetUser(User) returns (User);
}message User {// uid 是用户的唯一标识符,它必须大于999uint64 uid = 1 [(validate.rules).uint64.gt = 999];// email 是用户的电子邮件地址,它必须是一个有效的电子邮件地址string email = 2 [(validate.rules).string.email = true];// phone 是用户的电话号码,它必须符合中国大陆的手机号码格式string phone = 3 [(validate.rules).string = {pattern: "^1[3456789]\\d{9}$"}];
}

此时import语句会爆红,显示Cannot resolve import ‘validate.proto’,所以我们需要建立validate.proto文件。【注意:如果使用trpc 命令+ --validate参数,可忽略此步骤,trpc会拉取自己所依赖的validate.proto,原理:trpc-cmdline 工具内置了一份该文件。】
解决办法:

  1. 在本地GO Modules内找到 github.com/envoyproxy/protoc-gen-validate@v.xx.xx这个库中的validate/validate.proto文件,利用cv大法复制到proto/validate.proto文件中。
    在这里插入图片描述
  2. 从远程GitHub找到此项目该文件的代码:validate/validate.proto,利用cv大法复制到proto/validate.proto文件中。

2 执行命令生成对应go文件(x.validate.go)

trpc create -p user.proto \--rpconly \--nogomod \--mock=false \--protodir . \-o . \-- validate

3 server/server.go

package mainimport ("context""log""trpc.group/trpc-go/trpc-go""ziyi.com/04-validate/pb"
)func main() {//设置服务配置文件路径trpc.ServerConfigPath = "/Users/ziyi/GolandProjects/ziyifast-code_instruction/go-demo/go-trpc/04-validate/server/trpc_go.yaml"server := trpc.NewServer()pb.RegisterUserServiceService(server, &UserService{})if err := server.Serve(); err != nil {panic(err)}
}type UserService struct {
}func (s *UserService) GetUser(ctx context.Context, req *pb.User) (*pb.User, error) {if err := req.ValidateAll(); err != nil {return nil, err}log.Printf("pass.....")return req, nil
}

trpc_go.yaml:

server:service:#       服务名称- name: trpc.validate#      监听地址ip: 127.0.0.1#      服务监听端口port: 8088

4 client/client.go

package mainimport ("context""trpc.group/trpc-go/trpc-go/client""ziyi.com/04-validate/pb"
)func main() {cli := pb.NewUserServiceClientProxy(client.WithTarget("ip://localhost:8088"))req := new(pb.User)req.Email = "123@qq.com"req.Phone = "aaaa" //校验不通过//req.Phone = "18173827109" //校验通过req.Uid = 10001_, err := cli.GetUser(context.Background(), req)if err != nil {panic(err)}
}

5 验证

  • client中填写不满足格式的phone,校验不通过:
    在这里插入图片描述

实战二:自定义Validate规则

官方文档:https://go-kratos.dev/docs/component/middleware/validate/
代码地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-trpc/05-validate-self

步骤:

  1. 拷贝一份validate.proto到本地
  2. 修改validate.proto,添加或者修改规则
  3. 通过命令生成xxx.pb.validate.go之后,根据自己需求修改ValidateAll函数

案例:我现在需要定义一个新pstr选项,如果某个字段为String且为pstr,那么它的值只能在[“curry”, “tom”, "xujie]中三选一。
具体操作:
①本地添加规则在这里插入图片描述
②user.proto中设置pstr为true
在这里插入图片描述
③执行命令生成trpc代码以及对应校验文件
在这里插入图片描述
④修改user.pb.validate.go中ValidateAll方法
在这里插入图片描述
⑤编写client、server端代码,验证效果

  • 校验通过
    在这里插入图片描述
  • 校验失败
    在这里插入图片描述

参考文章:https://blog.csdn.net/MPY_3/article/details/140420543https://github.com/bufbuild/protoc-gen-validatehttps://pkg.go.dev/trpc.group/trpc/trpc-protocol/pb/go/trpc/validatehttps://go-kratos.dev/docs/component/middleware/validate/https://github.com/trpc-group/trpc-cmdline/blob/main/docs/examples/example-2/README.zh_CN.md#%E7%94%9F%E6%88%90-validatepbgo-%E6%96%87%E4%BB%B6

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com