在GoLang中将int64的Slice转换为字节数组,反之亦然

时间:2018-07-12 05:02:13

标签: go casting

我需要将int64的一个切片转换为golang中的字节数组。我可以对单个int64成功做到这一点

var p int64 = -3984171602573983744
fmt.Println(p)
cn := make([]byte, 8)
binary.LittleEndian.PutUint64(cn, uint64(p))
fmt.Println(cn)

如何为int64切片实现它?

更准确地说,我正在尝试在写至DB的库中调用一个函数,该函数将字节数组作为参数。我有一片int64,我需要将其转换为字节数组,反之亦然。这可能吗?

3 个答案:

答案 0 :(得分:1)

对于每个int64的循环,将其存储为binary.LittleEndian.PutUint64(cn[x:], yourUint64),其中x在循环时变为0、8、16...。您的cn应该足够大以容纳所有数据(将是8的倍数)。当您想阅读时,请执行相反的操作:x1 := binary.LittleEndian.Uint64(cn[n:n+8]),其中n变为0、1、2 ..

有关更简单的muxing-demuxing示例,请参见https://play.golang.org/p/YVQOAG8-Xlm

答案 1 :(得分:1)

例如,

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "math"
)

func main() {

    w64 := []int64{math.MinInt64, -1, 0, 1, math.MaxInt64}
    fmt.Println(w64)

    // Write []int64 to database []byte
    wbuf := new(bytes.Buffer)
    err := binary.Write(wbuf, binary.LittleEndian, w64)
    if err != nil {
        fmt.Println("binary.Write failed:", err)
    }
    db := wbuf.Bytes()
    fmt.Printf("% x\n", db)

    // Read database []byte to []int64
    rbuf := bytes.NewBuffer(db)
    r64 := make([]int64, (len(db)+7)/8)
    err = binary.Read(rbuf, binary.LittleEndian, &r64)
    if err != nil {
        fmt.Println("binary.Read failed:", err)
    }
    fmt.Println(r64)
}

游乐场:https://play.golang.org/p/4OscSOGZE52

输出:

[-9223372036854775808 -1 0 1 9223372036854775807]
00 00 00 00 00 00 00 80 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ff ff ff ff ff ff ff 7f
[-9223372036854775808 -1 0 1 9223372036854775807]

答案 2 :(得分:0)

如果您的计算机也是低端字节序(非常常见),则可以使用不安全的转换快速执行此操作(无需for循环)。这是两个示例函数,它们处理最长2 ^ 32字节的数组。您可以更改代码以处理更大的容量。

当然,它使用 unsafe 包,因此您可能需要修改它以返回副本,而不是直接使用内存。如果您不熟悉不安全的指针,则可以学习here

func bytesToInt64s(buf []byte) []int64 {
    if len(buf) < 1 << 16 {
        return (*[1 << 13]int64)(unsafe.Pointer(&buf[0]))[0 : len(buf)/8 : len(buf)/8]
    }
    l := len(buf)
    if l > 1 << 32 { // only use the first 2^32 bytes
       l = (1 << 32) - 1
    }
    return (*[1 << 29]int64)(unsafe.Pointer(&buf[0]))[0 : l / 8 : l / 8 ]
}

func int64sToBytes(buf []int64) []byte {
    if len(buf) < 1 << 13 {
        return (*[1 << 16]byte)(unsafe.Pointer(&buf[0]))[0 : len(buf)*8 : len(buf)*8]
    }
    l := len(buf) * 8
    if l > 1 << 32 { // only use the first 2^32 bytes
       l = (1 << 32) - 1
    }
    return (*[1 << 32]byte)(unsafe.Pointer(&buf[0]))[0 : l : l]
}