60

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.

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). Commented Mar 19, 2022 at 16:05

6 Answers 6

110

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
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, should i use the constants MaxVarintLenXX to determine the size of buffer before put ?
No, PutUint64 uses fixed length encoding. You only need MaxVarintLenXX when using PutVarint.
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)

4 Comments

I have slice of 6 bytes... is that possible? And I need timestamp from that... [224, 221, 199, 147, 195, 47] should get to 1632933900000
@ahmet, why do we need a byte slice of length 8 ? why not just 4 ?
@Gru, because an int64/uint64 uses 8 Bytes of storage. int32/uint32 only uses 4 Bytes.
Why do you need to AND with 0xFF?
7

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

2 Comments

what is the b := buf[:n] line for?
@JohnBalvinArias: it's because this example uses a variable length encoding
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

1 Comment

This can produce substantially more than 8 bytes, and the bytes are using all their bits for data.
5

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}

Comments

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

2 Comments

very inefficient answer
func Int64ToBytes(number int64) []byte { big := new(big.Int) return big.SetInt64(number).Bytes() }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.