逐字节比较varint编码的int64' s

时间:2013-05-08 14:01:51

标签: go byte

我正在使用levigo,即Go的leveldb绑定。我的密钥是int64,需要保持排序。默认情况下,leveldb使用字节比较器,所以我试图使用varint编码。

func i2b(x int64) []byte {
    b := make([]byte, binary.MaxVarintLen64)
    n := binary.PutVarint(b, x)
    return key[:n]
}

我的密钥没有正确排序。我写了以下内容作为测试。

var prev int64 = 0
for i := int64(1); i < 1e5; i++ {
    if bytes.Compare(i2b(i), i2b(prev)) <= 0 {
        log.Fatalf("bytewise: %d > %d", b2i(prev), i)
    }
    prev = i
}

输出 bytewise: 127 > 128

playground

我不确定问题出在哪里。我编码错了吗? varint不是正确的编码吗?

修改

BigEndian固定宽度编码是字节可比的

func i2b(x int64) []byte {
  b := make([]byte, 8)
  binary.BigEndian.PutUint64(b, uint64(x))
  return b
}

1 个答案:

答案 0 :(得分:1)

varint编码与字节顺序不相同* wrt与其讽刺的值的顺序。如何编写排序/整理功能(cmp如下)的一个选项是:

package main

import (
        "encoding/binary"
        "log"
)

func i2b(x int64) []byte {
        var b [binary.MaxVarintLen64]byte
        return b[:binary.PutVarint(b[:], x)]
}

func cmp(a, b []byte) int64 {
        x, n := binary.Varint(a)
        if n < 0 {
                log.Fatal(n)
        }

        y, n := binary.Varint(b)
        if n < 0 {
                log.Fatal(n)
        }

        return x - y
}

func main() {
        var prev int64 = 0
        for i := int64(1); i < 1e5; i++ {
                if cmp(i2b(i), i2b(prev)) <= 0 {
                        log.Fatal("fail")
                }
                prev = i
        }
}

Playground

(*)原因是(也)位fiddling performed