前述
golang grpc的API有2个版本:
-
v1:
- github.com/golang/protobuf(proto + grpc)
- github.com/grpc/grpc-go(grpc stup)
-
v2:
- google.golang.org/protobuf(proto) => https://github.com/google/protobuf => https://github.com/protocolbuffers/protobuf-go(go专用)
- google.golang.org/grpc(grpc, grpc stup) => https://github.com/google/grpc => https://github.com/grpc/grpc-go(go专用)
从github.com/golang/protobuf@v1.4.0后, golang grpc的源码生成工具归属到grpc-go的repository, 即所谓的v2版本. 以前用"protoc --go_out=plugins=grpc..."生成grpc的rpc stup代码, 现在要用"protoc --go_out=... --go-grpc_out=..."生成grpc的rpc stup代码!
新的protoc-gen-go插件已经不支持plugins选项:
--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC
参考
- grpc快速开始: https://grpc.io/docs/languages/go/quickstart/
- protobuf-go仓库: https://github.com/protocolbuffers/protobuf-go
- grpc-go仓库: https://github.com/grpc/grpc-go
实践
下载工具
windows:
set GO111MODULE=on
set GOPROXY=https://goproxy.cn
go get google.golang.org/protobuf google.golang.org/grpc
go install google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
或者
set GO111MODULE=on
set GOPROXY=https://goproxy.cn
go get google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
注意: go get实际等价于"git clone + go install", 如果package有main则会直接安装到bin. 因此只需将$GOPATH/bin添加PATH即可!
生成代码
- 编辑proto
syntax = "proto3";
package api;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
- 执行protoc
protoc --go_out=. --proto_path=. greeter.proto
protoc --go-grpc_out=. --proto_path=. greeter.proto
或者
protoc --go_out=. --go-grpc_out=. --proto_path=. greeter.proto
- 查看files
grpc-v2
|__api
|__greeter.pb.go
|__greeter.proto
|__greeter_grpc.pb.go
可见,之前grpc代码已经生成到_grpc.pb.go文件
创新
-
借鉴golang的Conditional compilation
- 参考: https://github.com/campoy/go-tooling-workshop/blob/master/2-building-artifacts/1-go-build.md
- file suffixes and build constraints, 文件后缀或编译约束
-
file suffixes
<file>_$GOOS_$GOARCH.go
- build constraints
// +build linux
// +build go1.8
// +build !go1.8
...
注意: golang的build constraints必须位于package前面, 而且与首条package之间保持至少一个空行! 否则会被认为是package的comment, 而不是file comment!
-
实现protobuf的build constraints
- 以+打头的comment
- file, package, message/field, service/method
-
实际需求
- 在message上标上"+content-type application/json"或"+content-type multipart/form-data".
// +content-type multipart/form-data message HelloReq { // +form-file string upload_file = 1; ... } service Greeter { // +http-path /demo/hello rpc SayHello (HelloRequest) returns (HelloReply); } 如果在message标上"+content-type multipart/form-data",则会按照form形式去解析, 各个字段根据field_name去解析相应的值. 默认是"application/json"!
可以考虑使用更短的命名: "+type form", "+type json", "+file", "+path /demo/hello"等等!
这些build constraints会影响产生的http代码!- 在service使用辅助API获取相应的值
ProtoKit.File(ctx, req.upload_file): name, size, reader
- 生成文件命名形式, 参考grpc生成文件: "_http.pb.go", 所以build contstraints统一加上http前缀是否会更清楚!
+http-type: from // multipart/form-data +http-type: json // application/json(默认!) +http-file // 标记字段是form-file获取, 可以使用ProtoKit.File()提取相关的临时文件 +http-path path // 标记service.method的http-path!
- 如何实现
- 将proto中的所有message/service都扫描到metadata中.
- 提供统一的数据结构, 可以template渲染, 也可以programma渲染!