Integer literals
Ah integer literals! Now we’re starting to get into the meat of the language.
Go lets us express integers in four bases. 10 (decimal) is by far the most common, followed by base 16 (hexidecimal). Base 8 (octal) and base 2 (binary) are also supported, but seen fairly rarely.
Here’s how the spec describes it:
An integer literal is a sequence of digits representing an integer constant. An optional prefix sets a non-decimal base:
0bor0Bfor binary,0,0o, or0Ofor octal, and0xor0Xfor hexadecimal. A single0is considered a decimal zero. In hexadecimal literals, lettersathroughfandAthroughFrepresent values10through15.
The astute reader may wonder why octal supports three prefixes, 0, 0o and 0O, whereas binary and hexidecimal each support only two (their upper- and lowercase- versions).
This is for historical reasons. Prior to the release of Go 1.13 in September 2019, there were no binary literals, and octal literals were indicated solely by the 0 prefix.
To make everything more consistent in Go 1.13, they added binary, with the respective 0b and 0B prefixes, and added the 0o and 0O prefixes for octal literals, to be consistent with the 0x and 0X prefixes already supported for hexidecimal literals.
These days, the plain 0 prefix should be considered obsolete, although it will continue to work indefinitely, if you’re using the standard gofmt tool (and you should be!), it will reformat any octal literals with the old bare 0 prefix to use 0o.
For readability, an underscore character
_may appear after a base prefix or between successive digits; such underscores do not change the literal’s value.
At the same time that Binary literals and standard Ocatl prefixes were added, they added the option to include arbitrary undescores (_) to literals. This should be used when it enhanches readability, such as to group by thousands when writing decimal literals.
int_lit = decimal_lit | binary_lit | octal_lit | hex_lit . decimal_lit = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] . binary_lit = "0" ( "b" | "B" ) [ "_" ] binary_digits . octal_lit = "0" [ "o" | "O" ] [ "_" ] octal_digits . hex_lit = "0" ( "x" | "X" ) [ "_" ] hex_digits . decimal_digits = decimal_digit { [ "_" ] decimal_digit } . binary_digits = binary_digit { [ "_" ] binary_digit } . octal_digits = octal_digit { [ "_" ] octal_digit } . hex_digits = hex_digit { [ "_" ] hex_digit } .42 4_2 0600 0_600 0o600 0O600 // second character is capital letter 'O' 0xBadFace 0xBad_Face 0x_67_7a_2f_cc_40_c6 170141183460469231731687303715884105727 170_141183_460469_231731_687303_715884_105727 _42 // an identifier, not an integer literal 42_ // invalid: _ must separate successive digits 4__2 // invalid: only one _ at a time 0_xBadFace // invalid: _ must separate successive digits
Quotes from The Go Programming Language Specification, Version of June 29, 2022