【问题标题】:How to write LEB128 in Go如何在 Go 中编写 LEB128
【发布时间】:2021-06-26 06:37:37
【问题描述】:

如何在 Go 中将整数写入 LEB128 格式?我正在尝试将 int32 编码为Minecraft VarInt,到目前为止,我已经尝试将 wiki 上的示例导入到 Go。我在测试时得到了错误的结果,wiki 说 -1 应该等于 [255 255 255 255 15],但我得到的是 [255 255 255 255 255]。我在这里做错了什么?

func WriteVarInt2(v int32) []byte{
   var out []byte
   c := 0
   for{
       currentByte := byte(v & 0b01111111)
       v >>= 7
       if v != 0 {
           currentByte |= 0b10000000
       }
       out = append(out, currentByte)
       c++

       if c >= 5 || v == 0{
           return out
       }
    }
}

【问题讨论】:

    标签: go binary varint


    【解决方案1】:

    问题在于移位操作。

    >>arithmetic shift 对,>>>logical shift 对。不同之处在于>> 引入了符号位(在左侧),而>>> 引入了零(无论符号位是什么)。

    LEB128的Varint的算法使用逻辑移位,Go的>>是算术移位。

    Go 中没有明显的逻辑移位,但如果你将数字视为无符号数,你会得到准确的结果:

    func WriteVarInt2(v_ int32) []byte {
        v := uint32(v_)
    
        // rest of your function unchanged
        // ...
    }
    

    测试它:

    fmt.Println(WriteVarInt2(-1))
    

    输出符合预期(在Go Playground 上尝试):

    [255 255 255 255 15]
    

    【讨论】: