解读 Golang Go语言标准库里的 varint 实现

最近发现 Golang 标准库竟然自带了 varint 的实现,代码位置在 encoding/binary/varint.go 。刚好借助 golang 标准库的 varint 源码,我们来系统地学习和梳理下 varint 。

熟悉 protobuf 的人肯定对 varint 不陌生,protobuf 里面除了带 fix (如 fixed32 、fixed64) 之外的整数类型, 都是 varint 编码。

varint 主要是为了解决两个问题:

空间效率:以 uint64 类型为例,可以表示的最大值为 18446744073709551615 。然而在实际业务场景中,我们通常处理的整数值远小于 uint64 的最大值。假设在我们的业务中,需要处理的整数值仅为 1 ,但在网络传输过程中,我们却需要使用 8 个字节来表示这个值。这就导致了大量的空间浪费,因为大部分字节并没有实际存储有效的信息。varint 编码通过使用可变长度的字节序列来表示整数,使得小的整数可以用更少的字节表示,提高空间效率。 兼容性:varint 使得我们可以在不改变编码 / 解码逻辑的情况下,处理不同大小的整数。这意味着我们可以在不破坏向后兼容性的情况下,将一个字段从较小的整数类型(如 uint32 )升级到较大的整数类型(如 uint64 ) 本文将通过分析 Golang 标准库自带的 varint 源码实现,介绍 varint 的设计原理以及 Golang 标准库是如何解决 varint 在编码负数时遇到的问题。

点击查看原文


解读 Golang Go语言标准库里的 varint 实现

更多关于解读 Golang Go语言标准库里的 varint 实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于解读 Golang Go语言标准库里的 varint 实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang(Go语言)标准库中,varint(可变长度整数)是一种用于高效编码整数的机制,尤其在需要序列化数据(如Protocol Buffers)时非常有用。varint通过占用不同数量的字节来表示不同范围的整数,从而节省了空间。

Go语言的encoding/binary包并不直接提供varint的编码和解码功能,但google.golang.org/protobuf/encoding/protowire等包中实现了这些功能。varint的编码规则简单而有效:

  1. 单字节整数:对于小的非负整数(0-127),varint直接使用该整数的一个字节表示。最高位(MSB)为0,表示这是一个单字节数。

  2. 多字节整数:对于较大的整数,varint使用多个字节表示。每个字节的最高位为1,表示还有后续字节;最低7位存储整数的一部分。最后一个字节的最高位为0,表示整数结束。

解码varint时,程序需要连续读取字节,直到遇到最高位为0的字节。解码过程中,程序将每个字节的最低7位按序拼接,构成完整的整数。

varint的优点在于它能根据整数的大小动态调整所需的字节数,对于小整数非常节省空间,而对于大整数也能保持较高的编码效率。这种特性使得varint在需要高效存储和传输整数的应用中非常受欢迎,如网络协议、数据存储系统等。

希望这能帮助你理解Go语言中varint的实现。如有进一步问题,欢迎继续探讨。

回到顶部