如何在Go语言中将int64转换为字节数组?

54

我有一个用int64表示的id。如何将其转换为[]byte?我看到二进制包可以将无符号整数进行转换,但我想确保不会破坏负数。


简而言之:intuint只是CPU如何“解释”底层位的方式。内存中底层位(11100101...)保持不变。如果是uint,则解释很直接。但如果是int,有几种方法可以将负数从/到位进行解释/表示(二进制补码是一种流行的方法)。 - starriet
6个回答

98

int64uint64 之间进行转换并不会改变符号位,只会改变它们的解释方式。

你可以使用正确的ByteOrder,使用 Uint64PutUint64 函数实现转换。

http://play.golang.org/p/wN3ZlB40wH

i := int64(-123456789)

fmt.Println(i)

b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(i))

fmt.Println(b)

i = int64(binary.LittleEndian.Uint64(b))
fmt.Println(i)

输出:

-123456789
[235 50 164 248 255 255 255 255]
-123456789

2
嗨,我应该使用常量 MaxVarintLenXX 来确定在放置之前缓冲区的大小吗? - user4466350
1
不,PutUint64 使用固定长度编码。只有在使用 PutVarint 时才需要 MaxVarintLenXX - Marcus Ilgner

8
您可以使用这个工具:
var num int64 = -123456789

b := []byte(strconv.FormatInt(num, 10))

fmt.Printf("num is: %v, in string is: %s", b, string(b))

输出:

num is: [45 49 50 51 52 53 54 55 56 57], in string is: -123456789

7

如果您不关心符号或端序(例如,用于映射键的哈希原因等),您可以简单地移位,然后将它们与0b11111111(0xFF)相与:

(假设v是int32类型)

b := [4]byte{
        byte(0xff & v),
        byte(0xff & (v >> 8)),
        byte(0xff & (v >> 16)),
        byte(0xff & (v >> 24))}

(对于int64/uint64,您需要拥有长度为8的字节切片)

我有一个6字节的切片...这可能吗?我需要从中获取时间戳...[224, 221, 199, 147, 195, 47]应该转换为1632933900000。 - Martin Zvarík
@ahmet,为什么我们需要一个长度为8的字节切片?为什么不只是4个? - Gru
@Gru,因为int64/uint64使用8个字节的存储空间,而int32/uint32只使用4个字节。 - Sebastian Dressler
为什么需要与0xFF进行AND运算? - Robert Zaremba

5

代码:

var num int64 = -123456789

// convert int64 to []byte
buf := make([]byte, binary.MaxVarintLen64)
n := binary.PutVarint(buf, num)
b := buf[:n]

// convert []byte to int64
x, n := binary.Varint(b)
fmt.Printf("x is: %v, n is: %v\n", x, n)

输出

x is: -123456789, n is: 4

b := buf[:n] 这行代码是干什么用的? - John Balvin Arias
@JohnBalvinArias:这是因为此示例使用变长编码。 - JimB

3
如果您需要在Go中实现类似于int.to_bytes(length, byteorder, *, signed=False)的功能,您可以这样做:
func uint64ToLenBytes(v uint64, l int) (b []byte) {
    b = make([]byte, l)

    for i := 0; i < l; i++ {
        f := 8 * i
        b[i] = byte(v >> f)
    }

    return
}

func int64ToLenBytes(v int64, l int) (b []byte) {
    return uint64ToLenBytes(uint64(v), l)
}

它将返回一个字节切片,例如:
ba = int64ToLenBytes(258, 3)
fmt.Printf("%#v\n", ba)

// output:
[]byte{0x2, 0x1, 0x0}

2
以下是一个简单的函数,可以达到您想要的效果:
func Int64ToBytes(number int64) []byte {
    big := new(big.Int)
    big.SetInt64(number)
    return big.Bytes()
}

非常低效的答案 - user1971598
func Int64ToBytes(number int64) []byte { big := new(big.Int) return big.SetInt64(number).Bytes() } - Jorvy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接