最近我在尝试使用go zero进行微服务开发,在尝试的过程中发现这个框架是非常简单易用的,但是也发现了一些额外的问题。比如说要引用googleapis或者一些常用的proto文件,如protovalidate等。
根据官网所述,目前go-zero的rpc是没有办法引入外部文件的,所以我思考了一个方法,在rpc生成代码的时候跳过生成pb.go文件,改成由buf生成,我们对goctl源码做一丢丢修改,然后得到新的goctl。
目前需要手动编译然后把goctl替换到自己的目录下,github.com/chaozwn/go-…
查看新的goctl rpc protoc功能
❯ goctl rpc protoc -h
Generate grpc code
Usage:
goctl rpc protoc [flags]
Examples:
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --client Whether to generate rpc client (default true)
-h, --help help for protoc
--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 priori
ty
-m, --multiple Generated in multiple rpc service mode
--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 priori
ty
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
-s, --skip_pb Whether to skip generating pb & grpc file
--style string The file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]
-v, --verbose Enable log output
--zrpc_out string The zrpc output directory
我们可以看到多了一个--skip_pb的选项,因为protoc去编译包含外部链接的proto文件会报错,所以我们用buf-cli托管。
安装buf, 参考官网: buf.build/docs/instal…
go install github.com/bufbuild/buf/cmd/buf@v1.35.0
安装完成运行buf, 出现以下输出就是正常工作。
❯ buf
Usage:
buf [flags]
buf [command]
Available Commands:
beta Beta commands. Unstable and likely to change
breaking Verify no breaking changes have been made
build Build Protobuf files into a Buf image
completion Generate auto-completion scripts for commonly used shells
config Work with configuration files
convert Convert a message between binary, text, or JSON
curl Invoke an RPC endpoint, a la 'cURL'
dep Work with dependencies
export Export proto files from one location to another
format Format Protobuf files
generate Generate code with protoc plugins
help Help about any command
lint Run linting on Protobuf files
ls-files List Protobuf files
push Push to a registry
registry Manage assets on the Buf Schema Registry
Flags:
--debug Turn on debug logging
-h, --help help for buf
--help-tree Print the entire sub-command tree
--log-format string The log format [text,color,json] (default "color")
--timeout duration The duration until timing out, setting it to zero means no timeout (default 2m0s)
-v, --verbose Turn on verbose mode
--version Print the version
Use "buf [command] --help" for more information about a command.
Sub-command required.
确保自己的goctl也可用,下面开启实战
- 先创建一个我们用的
proto文件
syntax = "proto3";
package greet;
option go_package="./greet";
// 外部proto文件
import "buf/validate/validate.proto";
message Request {
// 添加校验参数,如果ping的长度小于6,就会报错
string ping = 1 [(buf.validate.field).string = {
min_len: 6
}];
}
message Response {
string pong = 1;
}
service Greet {
rpc Ping(Request) returns(Response);
}
2.创建项目(在pb目录下执行)
goctl rpc protoc *.proto --go_out=../ --go-grpc_out=../ --zrpc_out=../ --style=goZero -s
这是项目的目录结构
3.初始化buf配置
buf config init
# buf.yaml
version: v2
lint:
use:
- DEFAULT
breaking:
use:
- FILE
# 添加下面的代码
deps:
- buf.build/bufbuild/protovalidate
4.安装依赖
buf dep update
目录下会生成buf.lock
# Generated by buf. DO NOT EDIT.
version: v2
deps:
- name: buf.build/bufbuild/protovalidate
commit: a6c49f84cc0f4e038680d390392e2ab0
digest: b5:e968392e88ff7915adcbd1635d670b45bff8836ec2415d81fc559ca5470a695dbdc30030bad8bc5764647c731079e9e7bba0023ea25c4e4a1672a7d2561d4a19
- 手动创建
buf.gen.yaml文件
version: v2
plugins:
- remote: buf.build/grpc/go
# Make sure to generate your grpc-go code to the same
# directory as protoc-gen-go
out: ../
- remote: buf.build/protocolbuffers/go
out: ../
ok, 一切准备就绪,后面我们全程都会用buf来管理我们的pb文件生成。
buf生成pb文件
buf generate --path ./pb/greet.proto --output ./pb˙
这是最新的目录结构
- 刷新依赖
go mod tidy
- 我们对
internal/server/greetServer.go稍作修改,后续的规模化更改完全可以通过模板来完成。不要忘记go mod tidy
// Code generated by goctl. DO NOT EDIT.
// Source: greet.proto
package server
import (
"context"
"rpc_test/greet"
"rpc_test/internal/logic"
"rpc_test/internal/svc"
// 对应依赖
"github.com/bufbuild/protovalidate-go"
"github.com/pkg/errors"
)
type GreetServer struct {
svcCtx *svc.ServiceContext
greet.UnimplementedGreetServer
}
func NewGreetServer(svcCtx *svc.ServiceContext) *GreetServer {
return &GreetServer{
svcCtx: svcCtx,
}
}
func (s *GreetServer) Ping(ctx context.Context, in *greet.Request) (*greet.Response, error) {
// 增加直接校验
v, _ := protovalidate.New()
if err := v.Validate(in); err != nil {
return nil, errors.Cause(err)
}
l := logic.NewPingLogic(ctx, s.svcCtx)
return l.Ping(in)
}
- 对系统进行测试, 移除掉
greet.yaml中etcd的配置
Name: greet.rpc
ListenOn: 0.0.0.0:8080