我正在使用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
我不确定问题出在哪里。我编码错了吗? varint不是正确的编码吗?
修改
BigEndian固定宽度编码是字节可比的
func i2b(x int64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(x))
return b
}
答案 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
}
}
(*)原因是(也)位fiddling performed。