How can I convert an int64 into a byte array in go?
Asked Answered
D

6

58

I have an id that is represented at an int64. How can I convert this to a []byte? I see that the binary package does this for uints, but I want to make sure I don't break negative numbers.

Dilatory answered 12/2, 2016 at 20:11 Comment(1)
in short: int or uint is just how CPU "interprets" the underlying bits. The underlying bits(11100101...) in the memory remain the same. If it's uint, the interpreting is straightforward. But if it's int, there are several ways to interpret/represent negative numbers from/to bits (two's complement is a popular way).Contracted
B
103

Converting between int64 and uint64 doesn't change the sign bit, only the way it's interpreted.

You can use Uint64 and PutUint64 with the correct ByteOrder

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)

output:

-123456789
[235 50 164 248 255 255 255 255]
-123456789
Beguine answered 12/2, 2016 at 20:37 Comment(2)
Hi, should i use the constants MaxVarintLenXX to determine the size of buffer before put ?Embryo
No, PutUint64 uses fixed length encoding. You only need MaxVarintLenXX when using PutVarint.Tarbes
G
8

If you don't care about the sign or endianness (for example, reasons like hashing keys for maps etc), you can simply shift bits, then AND them with 0b11111111 (0xFF):

(assume v is an int32)

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

(for int64/uint64, you'd need to have a byte slice of length 8)

Gerita answered 30/7, 2019 at 5:34 Comment(4)
I have slice of 6 bytes... is that possible? And I need timestamp from that... [224, 221, 199, 147, 195, 47] should get to 1632933900000Chutney
@ahmet, why do we need a byte slice of length 8 ? why not just 4 ?Forewing
@Gru, because an int64/uint64 uses 8 Bytes of storage. int32/uint32 only uses 4 Bytes.Kyleekylen
Why do you need to AND with 0xFF?Delivery
P
6

The code:

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)

outputs

x is: -123456789, n is: 4
Polio answered 26/12, 2017 at 12:17 Comment(2)
what is the b := buf[:n] line for?Kourtneykovac
@JohnBalvinArias: it's because this example uses a variable length encodingBeguine
W
6

You can use this too:

var num int64 = -123456789

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

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

Output:

num is: [45 49 50 51 52 53 54 55 56 57], in string is: -123456789
Wherewithal answered 11/8, 2018 at 23:2 Comment(1)
This can produce substantially more than 8 bytes, and the bytes are using all their bits for data.Calvinna
E
4

If you need a similar function as int.to_bytes(length, byteorder, *, signed=False) in Go you can do this:

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)
}

It will return a slice of bytes, for example:

ba = int64ToLenBytes(258, 3)
fmt.Printf("%#v\n", ba)

// output:
[]byte{0x2, 0x1, 0x0}
Easing answered 30/11, 2021 at 11:4 Comment(0)
A
1

Here's a simple function that should accomplish what you are wanting:

func Int64ToBytes(number int64) []byte {
    big := new(big.Int)
    big.SetInt64(number)
    return big.Bytes()
}
Amman answered 7/10, 2021 at 2:5 Comment(2)
very inefficient answerDumpcart
func Int64ToBytes(number int64) []byte { big := new(big.Int) return big.SetInt64(number).Bytes() }Amman

© 2022 - 2024 — McMap. All rights reserved.