# 简介
Protobuf从v2用到了v3,从C++用到了Golang,个人特别喜欢。3月2日,Go官宣,有了新版的API。[中文介绍](https://mp.weixin.qq.com/s/7w6BM23CXrXGx4HD8ZnzMg) 说实话,没有太看明白。的确有点尴尬,从14年用到了20年,不过想那么多干嘛。用就完了。
**因为V2 API所涉及的新功能,目前我均未使用到,本文并未介绍**
## 开始尝试
### 先来个小demo
**相关proto文件就不展示了**
**请注意引用新版API**,不是github,而是google.golang.org
**强烈建议大家开始使用go module,极度舒适,妈妈再也不担心我拉不到代码了!!!**
```go
package serverproto
import (
"google.golang.org/protobuf/proto"
"testing"
)
func TestBGFHead_GetUserId(t *testing.T) {
head := &BGFHead{}
head.UserId = 30020
proto.Marshal(head)
}
```
**go test**走起,然而竟然**报错啦**
```bash
[luojie@localhost serverproto]$ go test
# go/protobuf/serverproto [go/protobuf/serverproto.test]
./server_test.go:12:15: cannot use head (type *BGFHead) as type protoreflect.ProtoMessage in argument to "google.golang.org/protobuf/proto".Marshal:
*BGFHead does not implement protoreflect.ProtoMessage (missing ProtoReflect method)
FAIL go/protobuf/serverproto [build failed]
```
### 解决问题
因为是新版V2 API并不向前兼容V1的API,所以此处需要更新**protoc-gen-go** [说明文档](https://developers.google.com/protocol-buffers/docs/gotutorial)
```
go install google.golang.org/protobuf/cmd/protoc-gen-go
```
**使用了go module之后,install的速度也是快到飞起**
**!!!重新生成代码** 再次**go test**
```bash
[luojie@localhost serverproto]$ go test
PASS
ok go/protobuf/serverproto 0.003s
```
## 分析
### V1的go代码
```go
type BGFHead struct {
UserId int32 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
Cmd uint32 `protobuf:"varint,2,opt,name=cmd,proto3" json:"cmd,omitempty"`
TransTypes TransType `protobuf:"varint,3,opt,name=transTypes,proto3,enum=serverproto.TransType" json:"transTypes,omitempty"`
MsgType uint32 `protobuf:"varint,4,opt,name=msgType,proto3" json:"msgType,omitempty"`
SSerId int32 `protobuf:"varint,5,opt,name=sSerId,proto3" json:"sSerId,omitempty"`
SSerType ServerType `protobuf:"varint,6,opt,name=sSerType,proto3,enum=serverproto.ServerType" json:"sSerType,omitempty"`
DSerId int32 `protobuf:"varint,7,opt,name=dSerId,proto3" json:"dSerId,omitempty"`
DSerType ServerType `protobuf:"varint,8,opt,name=dSerType,proto3,enum=serverproto.ServerType" json:"dSerType,omitempty"`
Cooks []*CookInfo `protobuf:"bytes,9,rep,name=Cooks,proto3" json:"Cooks,omitempty"`
GroupId []int64 `protobuf:"varint,10,rep,packed,name=groupId,proto3" json:"groupId,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
}
```
### V2的go代码
```go
type BGFHead struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserId int32 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"` //用户id
Cmd uint32 `protobuf:"varint,2,opt,name=cmd,proto3" json:"cmd,omitempty"` //命令字
TransTypes TransType `protobuf:"varint,3,opt,name=transTypes,proto3,enum=serverproto.TransType" json:"transTypes,omitempty"` //发送类型
MsgType uint32 `protobuf:"varint,4,opt,name=msgType,proto3" json:"msgType,omitempty"` //消息类型
SSerId int32 `protobuf:"varint,5,opt,name=sSerId,proto3" json:"sSerId,omitempty"` //源服务 id
SSerType ServerType `protobuf:"varint,6,opt,name=sSerType,proto3,enum=serverproto.ServerType" json:"sSerType,omitempty"` //源服务 type
DSerId int32 `protobuf:"varint,7,opt,name=dSerId,proto3" json:"dSerId,omitempty"` //目标服务 id
DSerType ServerType `protobuf:"varint,8,opt,name=dSerType,proto3,enum=serverproto.ServerType" json:"dSerType,omitempty"` //目标服务 type
Cooks []*CookInfo `protobuf:"bytes,9,rep,name=Cooks,proto3" json:"Cooks,omitempty"` //我也不知道是干啥的
GroupId []int64 `protobuf:"varint,10,rep,packed,name=groupId,proto3" json:"groupId,omitempty"` //组id 与trans_types有关联
}
```
### 结论
- **V2生成的go代码含有proto文件中的注释**,个人非常喜欢,V1版本go代码不包含注释,复杂或者嵌套层次比较高的时候,没有注释,真是另人抓狂;
- 在官宣说明中有提到旧版无意义的字段也没有了;
- V2代码中新增了**state**,**sizeCache**,**unknownFields**三个字段,具体意义有待研究;
- V2中多引入两个包,分别为**protoreflect**,**protoimpl**;
## 应用
若现有项目还在用V1的API,新项目想使用V2的API的简单的方法
### 步骤
- 修改当前的protoc-gen-go为protoc-gen-goV1;
- 安装V2版本的protoc-gen-go;
- 将protoc-gen-go修改为protoc-gen-goV2;
- 将protoc-gen-goV1修改为protoc-gen-go;
**Windows下同理**
### 使用
#### V1版本
**和原来一样,没有任何改变**
#### V2版本
```bash
protoc --goV2_out=:. recharge.proto
```
有疑问加站长微信联系(非本文作者))