I find it weird that running big.NewInt(0).Bytes()
returns []
instead of [0]
. Is it really supposed to work that way?

- 41
- 1
-
4Not sure why exactly go does it, but it makes sense. From your playground link, you are not suprised that `Bytes()` does not return two bytes for 255. This number doesn't need to have any bits set in the second byte, so why return it as an insignificant 0, right? Similarly here, number 0 does not need to have any bits set even in the first byte. – Sergio Tulentsev Jun 09 '21 at 17:16
-
2"Is it really supposed to work that way?" is a question for the package author, but seeing as it has worked that way for a decade, I wouldn't think it's incorrect behavior; particularly as calling `SetBytes([]byte{})` yields `0`, making the behavior consistent. – Adrian Jun 09 '21 at 17:26
-
{} is a common mathematical representation for 0 so this looks very natural from a set theoretic perspective. – Volker Jun 09 '21 at 20:59
-
@SergioTulentsev Bytes() doesnt return two bytes because it returns absolute value of int. – Toni Jun 10 '21 at 11:39
-
@Toni: this is a _non sequitur_. Value 255 can be represented by `00 FF` (I'm using big endian here), just as well as by `FF` – Sergio Tulentsev Jun 10 '21 at 11:42
-
@SergioTulentsev I propably misunderstood something. Sorry about that. I expect `big.NewInt(255).Bytes()` to be `FF` and not `00 FF` just like I expect `big.NewInt(-255).Bytes()` to be `FF` and not `FF 01`. – Toni Jun 10 '21 at 12:35
-
@Toni: that is my point exactly. zero bytes in insignificant positions are not needed. And in case of `big.NewInt(0)` all bytes are insignificant zeroes. – Sergio Tulentsev Jun 10 '21 at 12:38
-
@SergioTulentsev I completely understand that zero bytes in insignificant positions are not needed. Im not sure my brains can agree that all bytes in case of `big.NewInt(0).Bytes()` are insignificant but I can live with that :) And there is always `big.NewInt(0).FillBytes(...)` too. Thanks @SergioTulentsev and all the others! – Toni Jun 10 '21 at 15:32
2 Answers
big.Int
is a struct. It's idiomatic to make the zero value useful whenever possible. big.Int
is no exception: The zero value for an Int
represents the value 0
.
It's an implementation detail, but the data of the Int
is stored in a slice. The zero value for slices is nil
, that is: no elements.
So this is very convenient, and very efficient. 0
is probably the most frequent value, and there may be cases where an initial big.Int
won't get changed, and so no slice for the internal representation will be allocated.
See related: Is there another way of testing if a big.Int is 0?

- 389,944
- 63
- 907
- 827
-
Its efficient if that 0 byte doesent matter. On the other hand if you need that 0 byte to be there then its inefficient to always check and handle that 0 value separately. But I quess its a tradeoff of that "efficiency". – Toni Jun 10 '21 at 11:11
From the documentation:
Bytes returns the absolute value of x as a big-endian byte slice.
The package API doesn't define how many bytes long the slice will be. In this case, it's using the smallest number of bytes needed to convey the whole number.
The more likely reason why this happens is an implementation detail: The big.Int
maintains the bytes of the number in a slice. nil
slices in Go (the zero value of a slice) have length 0. When a big.Int
value is initially created, we'd expect it to also have a value of 0
. Therefore, it simplifies the implementation if an empty slice internally corresponds to a numerical value of 0
, without needing to perform extra checks or padding.

- 7,530
- 2
- 17
- 33