使用Grpc需要有protoc的支持, 但默认安装的
/Go/bin
目录下只有go.exe
、gofmt.exe
两个可执行文件,因此要使用protoc
的话,需要自己去下载
-
在https://github.com/protocolbuffers/protobuf/releases中下载Windows64的压缩包,为
$protoc -go_out=. *.proto
使用到的命令可执行文件 -
编写
.proto
文件, 如下所示1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17syntax = "proto3";
# 注意, 这边使用的是go_package, 类似的还有java_package, 后面的参数是output_path和包名
option go_package = ".;geecachepb";
message Request{
string group = 1;
string key = 2;
}
message Response{
bytes value = 1;
}
service GroupCache{
rpc Get(Request) returns (Response);
} -
使用
protoc -go_out=. *.proto
命令,将.proto
转换成要使用的go文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.19.4
// source: geecachepb.proto
package geecachepb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Request struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Group string `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
}
// ... 省略更多 -
go get -u github.com/golang/protobuf/protoc-gen-go
安装使用xxxx.pb.go
文件的库 -
在业务代码中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40type PeerGetter interface {
Get(in *pb.Request, out *pb.Response) error
}
func (p *HttpPool) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// ...
body, err := proto.Marshal(&pb.Response{Value: view.ByteSlice()})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// ...
}
func (h *httpGetter) Get(in *pb.Request, out *pb.Response) error {
u := fmt.Sprintf(
"%v%v/%v",
h.baseURL,
url.QueryEscape(in.GetGroup()),
url.QueryEscape(in.GetKey()),
)
res, err := http.Get(u)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return fmt.Errorf("server return %v", res.Status)
}
bytes, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if err = proto.Unmarshal(bytes, out); err != nil {
return fmt.Errorf("decoding response body: %v", err)
}
return nil
}推荐风格
- 文件(Files)
- 文件名使用小写下划线的命名风格,例如 lower_snake_case.proto
- 每行不超过 80 字符
- 使用 2 个空格缩进
- 包(Packages)
- 包名应该和目录结构对应,例如文件在
my/package/
目录下,包名应为my.package
- 包名应该和目录结构对应,例如文件在
- 消息和字段(Messages & Fields)
- 消息名使用首字母大写驼峰风格(CamelCase),例如
message StudentRequest { ... }
- 字段名使用小写下划线的风格,例如
string status_code = 1
- 枚举类型,枚举名使用首字母大写驼峰风格,例如
enum FooBar
,枚举值使用全大写下划线隔开的风格(CAPITALS_WITH_UNDERSCORES ),例如 FOO_DEFAULT=1
- 消息名使用首字母大写驼峰风格(CamelCase),例如
- 服务(Services)
- RPC 服务名和方法名,均使用首字母大写驼峰风格,例如
service FooService{ rpc GetSomething() }
- RPC 服务名和方法名,均使用首字母大写驼峰风格,例如
- 文件(Files)
Author: Mrli
Link: https://nymrli.top/2022/02/22/protoc的使用/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.