最近发现 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 在编码负数时遇到的问题。