<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Golang on wsmの随记</title>
		<link>https://g0g.top/tags/golang/</link>
		<description>Recent content in Golang on wsmの随记</description>
		<generator>Hugo</generator>
		<language>zh-CN</language>
		
		
		
		
			<lastBuildDate>Thu, 28 Dec 2023 19:57:18 +0000</lastBuildDate>
		
			<atom:link href="https://g0g.top/tags/golang/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>ProtoBuf</title>
				<link>https://g0g.top/2023/12/protobuf-%E5%9F%BA%E7%A1%80/</link>
				<pubDate>Thu, 28 Dec 2023 19:57:18 +0000</pubDate>
				<guid>https://g0g.top/2023/12/protobuf-%E5%9F%BA%E7%A1%80/</guid>
				<description>&lt;p&gt;初次听闻 &lt;a href=&#34;https://protobuf.dev/&#34;&#xD;&#xA;  &#xD;&#xA;   target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;&gt;ProtoBuf&lt;/a&gt;，以为他是只是一种“二进制编码的 JSON 平替”。但事实与之相去甚远&lt;/p&gt;&#xA;&lt;h2 id=&#34;基本理解&#34;&gt;基本理解&lt;/h2&gt;&#xA;&lt;p&gt;在此节中我会将 JSON 与 ProtoBuf 进行横向对比。&lt;/p&gt;&#xA;&lt;p&gt;ProtoBuf 在设计上以“机器快速解析”为终极目标，并尽力减少不必要的数据（但不包括压缩）。为此它舍弃了 JSON 的以下优秀特性：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;自解释性：单个 JSON 字符串就可以解析出一个完整的以键值对为基础的对象；然而，ProtoBuf 将格式定义与数据&lt;strong&gt;分离&lt;/strong&gt;，protobuf 数据必须依赖某个目标语言中预定义的类似 &lt;code&gt;struct&lt;/code&gt; 的东西、配合 protobuf 的数据编码解码算法才能够解析。&lt;/li&gt;&#xA;&lt;li&gt;可读性：很明显，作为一种二进制编码，它是不可读的。&lt;/li&gt;&#xA;&lt;li&gt;简单性/易手搓：JSON 如此流行不可不归功于其语法的简洁明了，这也意味着对于一个新语言而言支持非常简单。而 ProtoBuf 定义了一个新的数据结构，有点点复杂，不太好实现。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;当然肯定有不少的优秀特性：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;高速解析：由于格式定义和数据的分离，格式定义被预编译进了代码内部，且以二进制编码数据，从而减少了解析时键名解析、类型判断、数值解析等开销，实现了 3-100 倍的解析性能提升。&lt;/li&gt;&#xA;&lt;li&gt;节省空间&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;：ProtoBuf 通过应用编号(Field Numbers)代替了键名，节省了寻键的开销和键的内存占用；ProtoBuf 用 Varint 和 ZigZag 减少了整数这种数据类型的内存占用。最重要的是，ProtoBuf 中所有部分都是可选的，实际传输中可以只传输要传输的那一部分，从而减少传输数据量；而不必像固定 struct 一样不论数据需不需要都会占固定内存。&lt;/li&gt;&#xA;&lt;li&gt;可变长度&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;：ProtoBuf LEB128 表示变长数据的长度，实现了非标记（例如 JSON的 &lt;code&gt;{}&lt;/code&gt;）变长度。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;个人感觉，ProtoBuf 是 Golang 开发者们为了 Golang 这样的静态语言而设计出的高效、扩展性强的结构化可选数据表示方式。如果把静态考虑在内，ProtoBuf 的确是最好的结构化&lt;strong&gt;可选&lt;/strong&gt;数据表示方式。&lt;/p&gt;&#xA;&lt;h2 id=&#34;打开方式&#34;&gt;打开方式&lt;/h2&gt;&#xA;&lt;p&gt;使用 ProtoBuf 需要三步：&lt;/p&gt;&#xA;&lt;ol start=&#34;0&#34;&gt;&#xA;&lt;li&gt;安装工具链，详见 &lt;a href=&#34;https://protobuf.dev/reference/&#34;&#xD;&#xA;  &#xD;&#xA;   target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;&gt;官网&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;在 &lt;code&gt;.proto&lt;/code&gt; 文件中编写你的 protobuf 格式&lt;/li&gt;&#xA;&lt;li&gt;用 &lt;code&gt;protoc&lt;/code&gt; 把 &lt;code&gt;.proto&lt;/code&gt; 文件编译成目标语言的代码&lt;/li&gt;&#xA;&lt;li&gt;在目标语言中引用编译出来的代码，引用 Google ProtoBuf 官方库，解析编码你的 ProtoBuf 数据&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;protobuf-语法&#34;&gt;ProtoBuf 语法&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;&#xA;&lt;p&gt;最基础的 protobuf 文件定义示例如下：&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
