Lexical elements: Integer literals
January 16, 2023
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:
0b
or0B
for binary,0
,0o
, or0O
for octal, and0x
or0X
for hexadecimal. A single0
is considered a decimal zero. In hexadecimal literals, lettersa
throughf
andA
throughF
represent values10
through15
.
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
Related Content

Empty structs
We finally we have enough knowledge for the EBNF format not to seem completely foreign, so let’s jump back and take a look at that, with the examples provided in the spec… Struct types … StructType = "struct" "{" { FieldDecl ";" } "}" . FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] . EmbeddedField = [ "*" ] TypeName [ TypeArgs ] . Tag = string_lit . // An empty struct.

Struct tags
Struct types … A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. An empty tag string is equivalent to an absent tag. The tags are made visible through a reflection interface and take part in type identity for structs but are otherwise ignored. struct { x, y float64 "" // an empty tag string is like an absent tag name string "any string is permitted as a tag" _ [4]byte "ceci n'est pas un champ de structure" } // A struct corresponding to a TimeStamp protocol buffer.

Struct method promotion
Yesterday we saw an example of struct field promotion. But methods (which we haven’t really discussed yet) can also be promoted. Struct types … Given a struct type S and a named type T, promoted methods are included in the method set of the struct as follows: If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.