当前位置: 首页 > news >正文

学习 Protobuf:序列化、反序列化及与 JSON 的对比

 一、Protobuf 简介

在构建高性能的分布式系统时,数据的序列化和反序列化是一个关键环节。

Protocol Buffers 是由 Google 开发的一种语言中立、平台中立、可扩展的序列化结构数据的方式, 它是一种高效的二进制序列化格式,适用于通信协议、数据存储等场合。它允许你定义结构化的数据,并生成多种语言的代码来读写这些数据。


 二、项目准备

1. 定义 .proto 文件

首先,我们需要定义一个 .proto 文件来描述我们的数据结构和服务接口。以下是一个简单的 helloworld.proto 文件示例:

syntax = "proto3";option go_package = "/proto1;proto1"; // 指定生成的 Go 包路径
//option go_package = ".;proto"; //这个可以生成在当前目录下message HelloRequest {string name = 1; // 字段编号从1开始
}

2. 使用 protoc 编译器生成 Go 代码

接下来,使用 protoc 编译器生成 Go 语言的源码:

protoc --go_out=. --go-grpc_out=. helloworld.proto

这条命令会根据 helloworld.proto 文件生成相应的 Go 代码,这些代码会被放置在指定的包目录中。

附录:项目结构


三、序列化与反序列化实践

下面我们将展示如何使用生成的 Go 代码进行序列化和反序列化操作。

✅ 示例代码

package mainimport ("awesomeProject1/rpc3/proto/proto1" // 使用生成的 proto1 包,其中包含 HelloRequest"fmt""google.golang.org/protobuf/proto" // 标准库,用于 Marshal/Unmarshal
)func main() {// 创建一个新的请求实例req := &proto1.HelloRequest{Name: "Bob",}// 序列化:将结构体转换为二进制数据data, err := proto.Marshal(req)if err != nil {panic(err)}fmt.Println("Serialized data:", data)// 反序列化:将二进制数据解析回结构体newReq := &proto1.HelloRequest{}err = proto.Unmarshal(data, newReq)if err != nil {panic(err)}fmt.Println("Deserialized name:", newReq.GetName())
}

 代码解释

代码片段解释
req := &proto1.HelloRequest{...}创建一个 HelloRequest 实例并初始化字段
data, err := proto.Marshal(req)将结构体序列化为二进制数据
fmt.Println("Serialized data:", data)打印序列化后的数据(注意:这是二进制形式,不可读)
newReq := &proto1.HelloRequest{}创建一个新的空结构体实例用于存储反序列化的结果
proto.Unmarshal(data, newReq)将二进制数据反序列化回结构体

四、 对比 Protobuf 和 JSON

为了更好地理解 Protobuf 的优势,我们将其与常见的 JSON 格式做对比。

1. 压缩比

  • Protobuf:由于采用二进制编码,数据更加紧凑。
  • JSON:基于文本的格式,数据体积相对较大。

2. 可读性

  • Protobuf:序列化后的数据是二进制格式,不适合人类直接阅读。
  • JSON:以文本形式存在,易于阅读和调试。

3. 性能

  • Protobuf:因为使用了二进制格式,序列化和反序列化速度更快。
  • JSON:需要额外的时间来进行字符串解析。

 示例对比

假设我们有如下 JSON 数据:

{"name": "Bob"
}

对应的 Protobuf 序列化后的数据可能看起来像这样(实际输出取决于具体实现):

Serialized data: [10 3 66 111 98]

虽然 Protobuf 的输出不如 JSON 直观,但它占用的空间更小,处理速度也更快,非常适合用于网络传输或持久化存储。


五、Protobuf 的优点

  1. 高效:相比 JSON,Protobuf 更加紧凑,减少了带宽消耗。
  2. 跨语言支持:支持多种编程语言,便于不同语言环境下的系统集成。
  3. 向前兼容性和向后兼容性:可以方便地更新消息格式而不会破坏现有服务。
  4. 自动代码生成:通过 protoc 工具自动生成代码,简化开发流程。

 学习建议

如果你刚开始接触 Protobuf,建议按照以下步骤学习:

  1. 编写 .proto 文件
    学习如何定义消息类型和服务接口。

  2. 安装 protoc 编译器
    确保你已经正确安装并配置了 protoc,以便能够生成目标语言的代码。

  3. 尝试序列化和反序列化
    使用生成的代码进行简单的序列化和反序列化练习。

  4. 探索更多功能
    探索 Protobuf 支持的其他特性,如枚举、嵌套消息等。

  5. 结合 gRPC 使用
    在微服务架构中使用 Protobuf 结合 gRPC,体验其强大之处。


六、总结

通过这篇博客,我们了解了如何使用 Protobuf 进行数据的序列化和反序列化,并与传统的 JSON 格式进行了比较。同时也了解到 Protobuf 是一种强大且灵活的数据序列化工具,特别适用于需要高效数据传输的场景。尽管 Protobuf 的数据不可读,但它的高效率和紧凑性使其成为构建分布式系统时的理想选择。

希望这篇文章能帮助你更好地掌握 Protobuf 的基本用法,Protobuf在rpc中的使用非常多,很多大公司都会选择开发自己的Protobuf,通过完善更多的功能,来应对更多的场景。

golang/protobuf: Go support for Google's protocol buffers
这是里面有Protobuf的源码,大家有能力之后,可以根据这个源码,写一套自己的插件。

http://www.xdnf.cn/news/1057843.html

相关文章:

  • Java中间件使用方式与实战应用
  • Oracle 的 TCP.SEND_TIMEOUT 参数
  • 【沉浸式解决问题】优化MySQL中多表union速度慢的问题
  • 【MATLAB去噪算法】基于VMD联合小波阈值去噪算法(第六期)
  • VS2022 C++动态库制作和使用指南
  • 【深度学习】TensorFlow全面指南:从核心概念到工业级应用
  • 【C++】vector的模拟实现(详解)
  • 记一次用飞算JavaAI助力项目部分重构的过程
  • 从C++编程入手设计模式——外观模式
  • 0616---0617C#实训课总结摘要
  • 【前端基础】摩天之建的艺术:html(上)
  • MIT 6.S081 2020 Lab8 locks 个人全流程
  • <script setup> 和在 <script> 中使用 setup() 函数有什么区别
  • vite的分包
  • 使用 React-i18next 在 TypeScript 的 Next.js 应用中实现国际化
  • ARM单片机启动流程(一)(万字解析,纯干货分享)
  • CVPR 2025最佳论文详解|VGGT:纯前馈Transformer架构,3D几何感知「大一统」模型来了!
  • 精益数据分析(108/126):媒体网站用户参与时间优化与分享行为解析
  • 【Unity笔记】Unity URP 渲染中的灯光数量设置— 场景、使用方法与渲染原理详解
  • Python 列表与元组的性能差异:选择合适的数据结构
  • 人机交互的趋势判断-范式革命的推动力量
  • SCRM客户关系管理软件的界面设计原则:提升用户体验与交互效率
  • 【Mysql】MySQL的MVCC及实现原理,核心目标与全流程图解
  • 获取ip地址安全吗?如何获取静态ip地址隔离ip
  • 常见航空数码相机
  • 基于SpringBoot的民宿管理平台-037
  • 【Linux指南】文件内容查看与文本处理
  • 操作系统引导和虚拟机(包含os结构,选择题0~1题无大题)
  • 编译链接实战(27)动态库实现变了,可执行程序需要重新编译吗
  • 互联网思维概念和落地