> For the complete documentation index, see [llms.txt](https://plainchant.gitbook.io/plainchant/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://plainchant.gitbook.io/plainchant/shu-ju-xing-ying-yong-xi-tong-she-ji/shu-ju-bian-ma-yu-yan-hua/protobuf-jian-jie.md).

# protobuf简介

\[TOC]

## \[protobuf简介]\(<https://developers.google.com/protocol-buffers/docs/proto3#top_of_page>)

protobuf是Google开发的一款跨语言，跨平台的序列化协议。 目前开源的protobuf共有两种协议规则，proto2和proto3，两者有部分数据不兼容，因此最好不要混用。

## protobuf语法

先看一个例子：

```
syntax = "proto3";

package protocol;
import "core/abc_types.proto";

option go_package = "github.com/BlockABC/wallet_permission_server/grpc/core";


enum AbcPermFlag {
    Null        = 0;//权限清空    Valid       = 1;//权限有效    Forbidden   = 2;//权限被禁}
/*** 代币和用户公用此权限单位，但是用户不区分平台，代币区分平台*/message AbcPermission {
    AbcPermFlag flag    = 1[json_name="flag"];          //权限标识,0表示清空,1表示有效,2表示封禁    string platform     = 3[json_name="platform"];      //平台信息，当设置平台时，允许用逗号区分多个平台进行批量设置}
```

`syntax`表示protobuf版本，这里使用第三版，官方现在也推荐使用proto3。 `package`定义了protobuf的包空间，避免命名冲突问题，这个通常会配合下面的go\_package使用，将相同类型数据导入到不同包中。 `option`是自定义选项，这里指定了go的包名，也可以指定其他语言的包名，具体的参数设置可以参考：\[Options]\(<https://developers.google.com/protocol-buffers/docs/proto3#options>) enum是枚举类型，只能是数字格式，且标签数值必须从0开始。 message是结构体类型，内部数据标签不能为0。 注意，同一消息体内，数字标签不能重复。

## protobuf支持类型

可以从官网查看[支持类型](https://developers.google.com/protocol-buffers/docs/proto3#scalar) 在proto3中还增加了map，any，oneof等类型。 此外还可以用repeated加在类型前面构建数组。

## protobuf编码

不同于json的字符串编码格式，protobuf是一种二进制编码方式。并且编码依赖设置的数字tag，也就是编码并不关心字段名，只关心tag和值，即便字段名变化依旧可以解析。 同理，如果变更了tag，则可能会导致解析的向前兼容问题，所以一旦tag固定后最好不要变动。 需要特别提醒的是标签 1–15 标识的字段编码仅占用 1 个字节（包括字段类型和标识标签），更多详细的信息请参考 [ProtoBuf 编码](https://developers.google.com/protocol-buffers/docs/encoding.html) 。 数值标签 16–2047 标识的字段编码占用 2 个字节。因此，你应该将标签 1–15 留给那些在你的消息类型中使用频率高的字段。记得预留一些空间（标签 1–15）给将来可能添加的高频率字段。

## 代码生成

代码生成需要安装[protoc](https://github.com/protocolbuffers/protobuf) golang还需安装\[proto-gen-go]\(<https://github.com/golang/protobuf>)。 可以用下面命令直接安装：

```
export GOPROXY=https://goproxy.io && GO111MODULE=on go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
export GOPROXY=https://goproxy.io && GO111MODULE=on go get -u github.com/micro/protobuf/{proto,protoc-gen-go}
export GOPROXY=https://goproxy.io && GO111MODULE=on go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
```

编译命令为：

```
protoc -I=. -I=/Users/plainchant/go/src --go_out=plugins=grpc,paths=source_relative:. hello.proto world.proto
```

`I`指向头文件地址，`go_out`表示输出go文件，`paths`表示使用相对路径，不会根据包内package生成绝对路径。

## 三方工具

gogoproto-gen-go是一款第三方的生成go代码的工具，它可以定制很多生成规则，生成的代码更美观，但是它是针对proto2开发，对proto3兼容性并不好，不建议使用。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://plainchant.gitbook.io/plainchant/shu-ju-xing-ying-yong-xi-tong-she-ji/shu-ju-bian-ma-yu-yan-hua/protobuf-jian-jie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
