扫码订阅《 》或入驻星球,即可阅读文章!

GOLANG ROADMAP

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
author-avatar

GOLANG ROADMAP


首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
  • 宝典简介

    • Go-gRPC 入门实践
  • 入门

    • 安装
    • gRPC简介
    • Protobuf语法
    • Protobuf⇢Go转换
  • 实践

  • 进阶

  • 多语言

  • 参考

扫码订阅《 》或入驻星球,即可阅读文章!

Protobuf⇢Go转换


jergoo

这里使用一个测试文件对照说明常用结构的protobuf到golang的转换。只说明关键部分代码,详细内容请查看完整文件。示例文件在proto/test目录下。

# Package

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

package test;
option go_package="test";
1
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

转换结果:

// 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"`
}
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

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

func (m *Test) GetAge() int32 {
	if m != nil {
		return m.Age
	}
	return 0
}
1
2
3
4
5
6

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

var Test_Status_name = map[int32]string{
	0: "OK",
	1: "FAIL",
}
var Test_Status_value = map[string]int32{
	"OK":   0,
	"FAIL": 1,
}
1
2
3
4
5
6
7
8

# 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

转换结果:

// 客户端接口
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)
}
1
2
3
4
5
6
7
8
9
10
11

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

  • Package
  • Message
  • Service