没有输出的输入是不完整的

0%

【微服务Go-micro第二篇】protoc到底干了啥

本篇文章主要介绍上一篇文章中利用protoc命令生成proto文件对应的另外两个文件的过程,
并简单介绍在实际业务中如何使用这两个文件。

先说结论

上一节我们通过下面的命令使得 user.proto

1
protoc --proto_path=. --micro_out=. --go_out=. proto/greeter.proto

生成了如下两个文件

1
user.pb.go  user.pb.micro.go

我们现在可以解释为什么会出现这种情况啦。

  1. protoc是一个代码生成的工具,它其实可以生成多种语言对应的文件,包括但是不限于c++,java,js,python,c#,当然也包括Go。
  2. 可以根据命令的参数格式发现–go_out实际上就是将生成的go语言的文件放到当前目录。然后–micro_out就是将生成的微服务的文件放到当前目录,所以就生成了上面的两个文件。
  3. 具体是怎么生成的呢?先说生成的go文件,这个文件我看了一下其实主要就是对于proto文件中的message进行编写。因为这个message将会是之后服务器和客户端进行通信的对象结构,所以有一些通用的方法,比如结构体定义,string方法等,在后面微服务的时候可以调用它。再说生成的micro文件,这个文件会针对于service中rpc的定义进行展开。会提供客户端和服务器端对应的api。
  4. 先说服务器端api的调用和对应api的使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type UserHandler interface {
RegisterUser(context.Context, *RegisterUserReq, *RegisterUserRsp) error
}

func RegisterUserHandler(s server.Server, hdlr UserHandler, opts ...server.HandlerOption) error {
type user interface {
RegisterUser(ctx context.Context, in *RegisterUserReq, out *RegisterUserRsp) error
}
type User struct {
user
}
h := &userHandler{hdlr}
return s.Handle(s.NewHandler(&User{h}, opts...))
}

type userHandler struct {
UserHandler
}

func (h *userHandler) RegisterUser(ctx context.Context, in *RegisterUserReq, out *RegisterUserRsp) error {
return h.UserHandler.RegisterUser(ctx, in, out)
}

server端api主要要创建一个服务,然后针对于这个服务提供handler方法,对应的handler要实现接口RegisterUser中的方法。

1
2
3
4
5
6
7
8
9
10
11
12
type User struct{}

func(user *User) RegisterUser(ctx context.Context, req *proto.RegisterUserReq, rsp *proto.RegisterUserRsp) (error){
rsp.Status ="ok"+req.Name
return nil
}

//创建服务
service := micro.NewService(
micro.Name("user"),
)
proto.RegisterUserHandler(service.Server(), new(User))

更详细的代码可以查看后面的main.go
5. 再说客户端的api和对应api的使用
生成的客户端的api如下所示

1
2
3
4
5
6
7
8
9
10
11
12
type UserService interface {
RegisterUser(ctx context.Context, in *RegisterUserReq, opts ...client.CallOption) (*RegisterUserRsp, error)
}

type userService struct {
c client.Client
name string
}

func NewUserService(name string, c client.Client) UserService{```}

func (c *userService) RegisterUser(ctx context.Context, in *RegisterUserReq, opts ...client.CallOption) (*RegisterUserRsp, error) {···}

所以在我们使用的时候,要首先通过NewUserService得到对应的service,然后调用RegisterUser方法来得到请求结果。

1
2
3
4
5

userService := proto.NewUserService("user", service.Client())

// Call the userregister
rsp, err := userService.RegisterUser(context.TODO(), &proto.RegisterUserReq{Name: "John"})

更加详细的代码可以参见后面client.go中的代码。

具体代码

1. user.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
syntax = "proto3";

service user{
rpc RegisterUser(RegisterUserReq) returns (RegisterUserRsp){}
}

message RegisterUserReq{
string name = 1;
}

message RegisterUserRsp{
string status = 1;
}

2. user.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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.21.0
// protoc v3.11.4
// source: proto/user.proto

package user

import (
proto "github.com/golang/protobuf/proto"
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)
)

// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4

type RegisterUserReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}

func (x *RegisterUserReq) Reset() {
*x = RegisterUserReq{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_user_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}

func (x *RegisterUserReq) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*RegisterUserReq) ProtoMessage() {}

func (x *RegisterUserReq) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use RegisterUserReq.ProtoReflect.Descriptor instead.
func (*RegisterUserReq) Descriptor() ([]byte, []int) {
return file_proto_user_proto_rawDescGZIP(), []int{0}
}

func (x *RegisterUserReq) GetName() string {
if x != nil {
return x.Name
}
return ""
}

type RegisterUserRsp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
}

func (x *RegisterUserRsp) Reset() {
*x = RegisterUserRsp{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_user_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}

func (x *RegisterUserRsp) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*RegisterUserRsp) ProtoMessage() {}

func (x *RegisterUserRsp) ProtoReflect() protoreflect.Message {
mi := &file_proto_user_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use RegisterUserRsp.ProtoReflect.Descriptor instead.
func (*RegisterUserRsp) Descriptor() ([]byte, []int) {
return file_proto_user_proto_rawDescGZIP(), []int{1}
}

func (x *RegisterUserRsp) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}

var File_proto_user_proto protoreflect.FileDescriptor

var file_proto_user_proto_rawDesc = []byte{
0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0x25, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73,
0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, 0x0f, 0x52, 0x65, 0x67,
0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74,
0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74,
0x61, 0x74, 0x75, 0x73, 0x32, 0x3c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0c,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x12, 0x10, 0x2e, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x10,
0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x73, 0x70,
0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
file_proto_user_proto_rawDescOnce sync.Once
file_proto_user_proto_rawDescData = file_proto_user_proto_rawDesc
)

func file_proto_user_proto_rawDescGZIP() []byte {
file_proto_user_proto_rawDescOnce.Do(func() {
file_proto_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_user_proto_rawDescData)
})
return file_proto_user_proto_rawDescData
}

var file_proto_user_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_proto_user_proto_goTypes = []interface{}{
(*RegisterUserReq)(nil), // 0: RegisterUserReq
(*RegisterUserRsp)(nil), // 1: RegisterUserRsp
}
var file_proto_user_proto_depIdxs = []int32{
0, // 0: user.RegisterUser:input_type -> RegisterUserReq
1, // 1: user.RegisterUser:output_type -> RegisterUserRsp
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}

func init() { file_proto_user_proto_init() }
func file_proto_user_proto_init() {
if File_proto_user_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterUserReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterUserRsp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_user_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_user_proto_goTypes,
DependencyIndexes: file_proto_user_proto_depIdxs,
MessageInfos: file_proto_user_proto_msgTypes,
}.Build()
File_proto_user_proto = out.File
file_proto_user_proto_rawDesc = nil
file_proto_user_proto_goTypes = nil
file_proto_user_proto_depIdxs = nil
}

3. user.pb.micro.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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: proto/user.proto

package user

import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)

import (
context "context"
api "github.com/micro/go-micro/v2/api"
client "github.com/micro/go-micro/v2/client"
server "github.com/micro/go-micro/v2/server"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// Reference imports to suppress errors if they are not otherwise used.
var _ api.Endpoint
var _ context.Context
var _ client.Option
var _ server.Option

// Api Endpoints for User service

func NewUserEndpoints() []*api.Endpoint {
return []*api.Endpoint{}
}

// Client API for User service

type UserService interface {
RegisterUser(ctx context.Context, in *RegisterUserReq, opts ...client.CallOption) (*RegisterUserRsp, error)
}

type userService struct {
c client.Client
name string
}

func NewUserService(name string, c client.Client) UserService {
return &userService{
c: c,
name: name,
}
}

func (c *userService) RegisterUser(ctx context.Context, in *RegisterUserReq, opts ...client.CallOption) (*RegisterUserRsp, error) {
req := c.c.NewRequest(c.name, "User.RegisterUser", in)
out := new(RegisterUserRsp)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return nil, err
}
return out, nil
}

// Server API for User service

type UserHandler interface {
RegisterUser(context.Context, *RegisterUserReq, *RegisterUserRsp) error
}

func RegisterUserHandler(s server.Server, hdlr UserHandler, opts ...server.HandlerOption) error {
type user interface {
RegisterUser(ctx context.Context, in *RegisterUserReq, out *RegisterUserRsp) error
}
type User struct {
user
}
h := &userHandler{hdlr}
return s.Handle(s.NewHandler(&User{h}, opts...))
}

type userHandler struct {
UserHandler
}

func (h *userHandler) RegisterUser(ctx context.Context, in *RegisterUserReq, out *RegisterUserRsp) error {
return h.UserHandler.RegisterUser(ctx, in, out)
}

4. main.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
package main

import(
"context"
micro "github.com/micro/go-micro/v2"
proto "datatown/proto"
"fmt"
)

type User struct{

}

func(user *User) RegisterUser(ctx context.Context, req *proto.RegisterUserReq, rsp *proto.RegisterUserRsp) (error){
rsp.Status ="ok"+req.Name
return nil
}

func main() {
// Create a new service. Optionally include some options here.
service := micro.NewService(
micro.Name("user"),
)

// Init will parse the command line flags.
service.Init()

// Register handler
proto.RegisterUserHandler(service.Server(), new(User))

// Run the server
if err := service.Run(); err != nil {
fmt.Println(err)
}
}

5. client.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
package main

import(
"fmt"
"context"
micro "github.com/micro/go-micro/v2"
proto "datatown/proto"
)

func main() {
// Create a new service
service := micro.NewService(micro.Name("user.client"))
// Initialise the client and parse command line flags
service.Init()

// Create new user service client
userService := proto.NewUserService("user", service.Client())

// Call the userregister
rsp, err := userService.RegisterUser(context.TODO(), &proto.RegisterUserReq{Name: "John"})
if err != nil {
fmt.Println(err)
}

// Print response
fmt.Println(rsp.Status)
}