惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 热门话题
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
Vercel News
Vercel News
MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
C
CERT Recently Published Vulnerability Notes
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Webroot Blog
Webroot Blog
B
Blog
WordPress大学
WordPress大学
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
F
Full Disclosure
V
V2EX
H
Help Net Security
Stack Overflow Blog
Stack Overflow Blog
H
Hacker News: Front Page
小众软件
小众软件
Latest news
Latest news
Google DeepMind News
Google DeepMind News
S
Secure Thoughts
I
InfoQ
P
Palo Alto Networks Blog
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
博客园 - 【当耐特】
D
Docker
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Privacy & Cybersecurity Law Blog
G
Google Developers Blog
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
NISL@THU
NISL@THU
M
MIT News - Artificial intelligence
Schneier on Security
Schneier on Security
The Last Watchdog
The Last Watchdog
月光博客
月光博客
S
Securelist
Y
Y Combinator Blog
量子位
Security Archives - TechRepublic
Security Archives - TechRepublic
Microsoft Security Blog
Microsoft Security Blog
Security Latest
Security Latest

博客园 - HorseShoe2016

Ethereum 学习笔记 ---- Solidity 数据位置(Calldata, Memory, Storage)编码与布局全解析 vscode 禁用警告提示音 浏览器加载 HTML 页面并执行 Javascript 的流程图 Ethereum学习笔记 ---- 多重继承中的 C3线性化算法 Ethereum学习笔记 ---- 使用 Remix 调试功能理解 bytes 在 memory 中的布局 Ethereum学习笔记 ---- 通过 Event 学习《合约ABI规范》 Javascript: Blob, File/FileReader, ArrayBuffer, ReadableStream, Response 转换方法 vscode 无法调试 golang testify suite 中的单个 test 的解决办法 纯js实现 vue 组件 与 vue 单文件组件对比 一个简单的 indexedDB 应用示例 html 元素的 onEvent 与 addEventListener vue3 defineComponent: 使用纯 Javascript 定义组件 vue3 动态编译组件失败:Component provided template option but runtime compilation is not supported in this build of Vue Javascript Object 中,isExtensible/isSealed/isFrozen 的对比 mini-vue: 响应式数据的实现 手写Promise vscode vue 插件与 emmet、tailwind css 插件冲突的解决方案 Python 安装依赖包,出现 ssl.SSLCertVerificationError 的问题,解决方法 CentOS7 源码编译安装 Python 3.8.10,开启 SSL 功能
Protocol Buffer Go (proto3) - macos 搭建 protocol buffer 环境 + Encoding 实验
HorseShoe2016 · 2022-07-10 · via 博客园 - HorseShoe2016

macos 搭建 protocol buffer 环境

  • 安装 protoc

    brew install protobuf
    
  • 为 protoc 安装 go 插件

    $ go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest \
                 github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
    
    $ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
    
    $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
    

    这些插件不能在同一条命令里执行安装,因为同一条 go install 命令安装的插件,必须是在同一个 module 下的,某则会有错误提示: All packages must be provided by the same module.

Encoding实验

参考文档: Encoding

  • protocol buffer wire types 列表
    Type Meaning Used For
    0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
    1 64-bit fixed64, sfixed64, double
    2 Length-delimited string, bytes, embedded messages, packed repeated fields
    3 Start group groups (deprecated)
    4 End group groups (deprecated)
    5 32-bit fixed32, sfixed32, float
  • 定义 proto 如下
    syntax = "proto3";
    
    message StringMessage {
      string value = 1;
      int32 count = 2;
      int64 num = 3;
      string home = 4;
    }
    
    message StringMessage2 { string val = 1; }
    
    使用 protoc 将 protofile.proto 转换成 golang 结构
    protoc  \
      --go_out=./gen/ \
      --go_opt paths=source_relative \
      protofile.proto
    
    生成 protofile.pb.go 如下:
    type StringMessage struct {
    	state         protoimpl.MessageState
    	sizeCache     protoimpl.SizeCache
    	unknownFields protoimpl.UnknownFields
    
    	Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
    	Count int32  `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
    	Num   int64  `protobuf:"varint,3,opt,name=num,proto3" json:"num,omitempty"`
    	Home  string `protobuf:"bytes,4,opt,name=home,proto3" json:"home,omitempty"`
    }
    
    type StringMessage2 struct {
    	state         protoimpl.MessageState
    	sizeCache     protoimpl.SizeCache
    	unknownFields protoimpl.UnknownFields
    
    	Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"`
    }
    
  • main函数
    package main
    
    import (
    	"fmt"
    
    	pb "path_to_generated_pb_go"
    	"google.golang.org/protobuf/proto"
    )
    
    func main() {
        	msg := &pb.StringMessage{Value: "abc", Count: 127, Num: 128, Home: "China"}
        	fmt.Println("msg:")
        	fmt.Println(msg)
        	out, _ := proto.Marshal(msg)
        	fmt.Println(out)
        	msg2 := &pb.StringMessage2{}
        	proto.Unmarshal(out, msg2)
        	fmt.Println("\nmsg2:")
        	fmt.Println(msg2)
        	out2, _ := proto.Marshal(msg2)
        	fmt.Println(out2)
    }
    
  • 执行结果
    msg:
    value:"abc" count:127 num:128 home:"China"
    [10 3 97 98 99 16 127 24 128 1 34 5 67 104 105 110 97]
    
    msg2:
    val:"abc" 2:127 3:128 4:"China"
    [10 3 97 98 99 16 127 24 128 1 34 5 67 104 105 110 97]
    
  • 序列化结果分析
    • [10 3 97 98 99] 这一段
      • 10 由 StringMessage.Value 的 fieldNumber 1 和 wireType 2 (string) 构成:
        (1<<3|2) = 10
      • 3 表示接下来3个字节构成字符串
      • 97 98 99abc 的 ASCII 编码
    • [16 127] 这一段
      • 16 由 StringMessage.Count 的 fieldNumber 2 和 wireType 0 (int32) 构成:
        (2<<3|0) = 16
      • 127 用一个字节足以表示127
    • [24 128 1] 这一段
      • 24 由 StringMessage.Num 的 filedNumber 3 和 wireType 0 (int64) 构成:
        (3<<3|0) = 24
      • 128 1 二进制为 1000 0000 0000 0001,根据 protobuf 的规则,首个 1 表示后续字节依然要跟本字节一起表示数字;第二个字节的首个 bit 为 0,表明后续自己跟本字段无关。且 protobuf 将数字按照 bigEndian 存储,所以解码后的数字为 000 0001 000 0000,值为 128
    • [34 5 67 104 105 110 97] 这一段
      • 34 由 StringMessage.Home 的 fileNumber 4 和 wireType 2 (string) 构成:
        (4<<3|2) = 34
      • 5 表示接下来5个字节构成字符串
      • 67 104 105 110 97China 的 ASCII 编码
    • 关于 msg2
      使用 StringMessage 的序列化结果,反序列化到 StringMessage2, 虽然 StringMessage2 中不包含 filedNumber 为 2, 3, 4 的字段,但是 StringMessage2 的实例 msg2 中依然可以在其中保留相关字段的内容。看一下 protobuf 根据 .proto 生成的 StringMessage2 的定义:
      type StringMessage2 struct {
      	state         protoimpl.MessageState
      	sizeCache     protoimpl.SizeCache
      	unknownFields protoimpl.UnknownFields
      
      	Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"`
      }
      
      这些未在 StringMessage2 中定义的内容,就保存在 unknownFields 字段里,重新序列化后,可以得到跟原始内容相同的序列化结果。

posted on 2022-07-10 20:05  HorseShoe2016  阅读(324)  评论()    收藏  举报