Description
This has come up before, specifically during discussions of #19308 and #28256. I am writing this down so we have a place for discussing this independently. I have no strong feelings about this proposal either way.
Proposal
This is a fully backward-compatible proposal for permitting the use of a blank (_) as a separator in number literals. Specifically, we change the integer literal syntax such that we also allow a "_" after the first digit (the change is the extra "_"):
int_lit = decimal_lit | octal_lit | hex_lit .
decimal_lit = ( "1" … "9" ) { decimal_digit | "_" } .
octal_lit = "0" { octal_digit | "_" } .
hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit | "_" } .
And we change the floating-point number literal syntax correspondingly (the change is the extra "_"):
float_lit = decimals "." [ decimals ] [ exponent ] | decimals exponent | "." decimals [ exponent ] .
decimals = decimal_digit { decimal_digit | "_" } .
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals .
For complex number literals the change is implied by the change to floating-point literals.
Examples:
123_456_789
1_000_000_000
0b0110_1101_1101_0010 // if we had binary integer literals
0xdead_beef
3.1415_9265
but also:
0___ // 0
0_77 // 77 decimal, or perhaps not permitted (TBD)
01_10 // 0110 (octal)
1_2__3___ // 123
0x1_23_0 // 0x1230
0__.0__e-0__ // 0.0e-0
Discussion
The notation follows more or less the syntax used in other languages (e.g., Swift).
The implementation is straight-forward (a minor change to the number scanner). As the examples show, the separator, if judiciously used, may improve readability; or it may degrade it significantly.
A tool (go vet) might impose restrictions on how the separator is used for readability.