go18/skills/rpc/protobuf/README.md

158 lines
4.3 KiB
Markdown
Raw Normal View History

2025-08-24 11:35:52 +08:00
# protobuf
```go
// RPC 协议,约束服务端的实现,约束 客户端的调用
type HelloService interface {
Hello(ctx context.Context, request string) (string, error)
}
```
+ RPC方法的定义
+ PRC数据结构的定义
## 插件安装
```sh
➜ protobuf go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go: downloading google.golang.org/protobuf v1.36.8
➜ protobuf go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go: downloading google.golang.org/grpc v1.75.0
```
## 接口声明
```proto
syntax = "proto3";
package hello;
option go_package="122.51.31.227/go-course/go18/skills/rpc/protobuf/hello_service";
// The HelloService service definition.
service HelloService {
// rpc 声明接口
rpc Hello (Request) returns (Response);
}
message Request {
string value = 1;
}
message Response {
string value = 1;
}
```
## 使用protobuf 定义数据结构
使用protoc-gen-go 插件来生成struct
```proto
message Request {
string value = 1;
}
message Response {
string value = 1;
}
```
```sh
# -- go_out 是参数, go out: go使用go语言插件(protoc-gen-go), go语言插件的参数 out
# out: 生成的代码放哪个目录, 默认项目根目录
# opt: module="xxx", 用于指定文件所属go module
# 应用使用了module="xxx"最好在工程根目录执行
# -I: 指定protobuf include的其他包的搜索位置, 通常情况 项目根目录比较合适
# cd go18
protoc -I=. --go_out=. --go_opt=module="122.51.31.227/go-course/go18" skills/rpc/protobuf/hello_service/interface.proto
```
interface.pb.go
```go
type Request struct {
state protoimpl.MessageState `protogen:"open.v1"`
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
type Response struct {
state protoimpl.MessageState `protogen:"open.v1"`
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
```
## 使用protobuf 定义RPC (grpc)
使用 protoc-gen-go-grpc来生成 接口描述(service定义相关部分)
```proto
// The HelloService service definition.
service HelloService {
// rpc 声明接口
rpc Hello (Request) returns (Response);
}
```
```sh
# -- go_out 是参数, go out: go使用go语言插件(protoc-gen-go), go语言插件的参数 out
# out: 生成的代码放哪个目录, 默认项目根目录
# opt: module="xxx", 用于指定文件所属go module
# 应用使用了module="xxx"最好在工程根目录执行
# -I: 指定protobuf include的其他包的搜索位置, 通常情况 项目根目录比较合适
# cd go18
protoc -I=. --go-grpc_out=. --go-grpc_opt=module="122.51.31.227/go-course/go18" skills/rpc/protobuf/hello_service/interface.proto
```
interface_grpc.pb.go
```go
// 服务端接口
// HelloServiceServer is the server API for HelloService service.
// All implementations must embed UnimplementedHelloServiceServer
// for forward compatibility.
//
// The HelloService service definition.
type HelloServiceServer interface {
// rpc 声明接口
Hello(context.Context, *Request) (*Response, error)
mustEmbedUnimplementedHelloServiceServer()
}
// 客户端接口
// HelloServiceClient is the client API for HelloService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// The HelloService service definition.
type HelloServiceClient interface {
// rpc 声明接口
Hello(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}
// 客户端的具体实现
type helloServiceClient struct {
cc grpc.ClientConnInterface
}
func NewHelloServiceClient(cc grpc.ClientConnInterface) HelloServiceClient {
return &helloServiceClient{cc}
}
func (c *helloServiceClient) Hello(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Response)
err := c.cc.Invoke(ctx, HelloService_Hello_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
```
## 服务端实现接口注册给grpc服务
## 其他服务 使用生成的client调用grpc服务的方法