Shane Hou
Shane Hou

Reputation: 5018

binary.Uvarint got wrong int value than expected

I have a 4 length slice stored an int value like this:

[159 124 0 0]

Then I tried val, encodeBytes := binary.Uvarint(slice), but got wrong val:

val = 15903, encodebytes = 2

The correct val should be 31903, what's wrong with it?

Here is the code:

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

Upvotes: 2

Views: 846

Answers (3)

Emil L
Emil L

Reputation: 21081

According to the binary package documentation the encoding used to interpret the byte sequence is the one available here. It specifies that bytes are interpreted as:

Each byte in a varint, except the last byte, has the most significant bit (msb) set – this indicates that there are further bytes to come. The lower 7 bits of each byte are used to store the two's complement representation of the number in groups of 7 bits, least significant group first.

The binary representation of [159 124 0 0] is:

1001  1111 , 0111 1100 , 0000  0000, 0000 0000

The most significant bit (MSB) of the first byte is set so the second byte will also be interpreted. The second bytes MSB is not set so the remaining bytes are ignored.

By dropping the MSB of the bytes interpreted the bits we get:

001 1111 , 111 1100 

These two groups are then reversed before being interpreted as the number:

111 1100 , 001 1111

concatenated:
0011 1110 0001 1111

Converting this back to decimal we get:

1 + 2 +4 + 8 + 16 + 0 + 0 + 0 + 0 + 512 + 1024 + 2048 + 4096 + 8192 = 15903

As James' and peterSO's post indicates you probably want to use binary.LittleEndian.Uint32 instead.

Upvotes: 1

James Henstridge
James Henstridge

Reputation: 43909

From the expected result, it sounds like you're trying to decode a little endian 32-bit integer. The binary.Uvarint function is the wrong one for the job though, since it decodes the variable length integer encoding used by the Protocol Buffers specification.

Instead, try using binary.LittleEndian.Uint32():

val := binary.LittleEndian.Uint32(slice)

Upvotes: 1

peterSO
peterSO

Reputation: 166626

For example,

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    bytes := []byte{159, 124, 0, 0}
    integer := int(binary.LittleEndian.Uint32(bytes))
    fmt.Println(bytes, integer)
}

Output:

[159 124 0 0] 31903

Upvotes: 1

Related Questions