演示 定义和编写proto文件

创建 string.proto 文件

在proto文件中使用 package 关键字声明包名,默认转换成 go 中的包名与此一致,如果需要指定不一样的包名,可以使用go_package 选项。

示例解释:
option go_package="./;main" 是指生成的文件要放在 当前目录,main指生成的文件包名是main。

1、测试转换示例

syntax = "proto3";

package pb;

option go_package = "./pb";

service StringService{
    rpc Concat(StringRequest) returns (StringResponse) {}
    rpc Diff(StringRequest) returns (StringResponse) {}

}

message StringRequest {
    string A = 1;
    string B = 2;
}

message StringResponse {
    string Ret = 1;
    string err = 2;
}

进行转换

protoc --go_out=plugins=grpc:. pb/string.proto

转换成功后,会在pb目录下生成 string.pb.go 文件,结果如下:

package pb

import (
    context "context"
    grpc "google.golang.org/grpc"
    codes "google.golang.org/grpc/codes"
    status "google.golang.org/grpc/status"
    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 StringRequest struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    A string `protobuf:"bytes,1,opt,name=A,proto3" json:"A,omitempty"`
    B string `protobuf:"bytes,2,opt,name=B,proto3" json:"B,omitempty"`
}
//...... 省略

2、测试 Message 示例:

proto 中的message对应go中的struct,全部使用驼峰命名规则。嵌套定义的message,enum转换为go之后,名称变为Parent_Child结构。

示例 proto:

// Test 测试
message Test {
    int32 age = 1;
    int64 count = 2;
    double money = 3;
    float score = 4;
    string name = 5;
    bool fat = 6;
    bytes char = 7;
    // Status 枚举状态
    enum Status {
        OK = 0;
        FAIL = 1;
    }
    Status status = 8;
    // Child 子结构
    message Child {
        string sex = 1;
    }
    Child child = 9;
    map<string, string> dict = 10;
}

转换结果:

// Status 枚举状态
type Test_Status int32

const (
    Test_OK   Test_Status = 0
    Test_FAIL Test_Status = 1
)

// Test 测试
type Test struct {
    Age    int32       `protobuf:"varint,1,opt,name=age" json:"age,omitempty"`
    Count  int64       `protobuf:"varint,2,opt,name=count" json:"count,omitempty"`
    Money  float64     `protobuf:"fixed64,3,opt,name=money" json:"money,omitempty"`
    Score  float32     `protobuf:"fixed32,4,opt,name=score" json:"score,omitempty"`
    Name   string      `protobuf:"bytes,5,opt,name=name" json:"name,omitempty"`
    Fat    bool        `protobuf:"varint,6,opt,name=fat" json:"fat,omitempty"`
    Char   []byte      `protobuf:"bytes,7,opt,name=char,proto3" json:"char,omitempty"`
    Status Test_Status `protobuf:"varint,8,opt,name=status,enum=test.Test_Status" json:"status,omitempty"`
    Child  *Test_Child `protobuf:"bytes,9,opt,name=child" json:"child,omitempty"`
    Dict   map[string]string `protobuf:"bytes,10,rep,name=dict" json:"dict,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}

// Child 子结构
type Test_Child struct {
    Sex string `protobuf:"bytes,1,opt,name=sex" json:"sex,omitempty"`
}

除了会生成对应的结构外,还会有些工具方法,如字段的getter:

func (m *Test) GetAge() int32 {
    if m != nil {
        return m.Age
    }
    return 0
}

枚举类型会生成对应名称的常量,同时会有两个map方便使用:

var Test_Status_name = map[int32]string{
    0: "OK",
    1: "FAIL",
}
var Test_Status_value = map[string]int32{
    "OK":   0,
    "FAIL": 1,
}

3、测试 Service

定义一个简单的Service,TestService有一个方法Test,接收一个Request参数,返回Response:

// TestService 测试服务
service TestService {
    // Test 测试方法
    rpc Test(Request) returns (Response) {};
}

// Request 请求结构
message Request {
    string name = 1;
}

// Response 响应结构
message Response {
    string message = 1;
}

转换结果:

// 客户端接口
type TestServiceClient interface {
    // Test 测试方法
    Test(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}

// 服务端接口
type TestServiceServer interface {
    // Test 测试方法
    Test(context.Context, *Request) (*Response, error)
}

生成的go代码中包含该Service定义的接口,客户端接口已经自动实现了,直接供客户端使用者调用,服务端接口需要由服务提供方实现。

作者:joker.liu  创建时间:2023-05-18 16:16
最后编辑:joker.liu  更新时间:2023-05-22 15:16