Go Practices 101
Theme: dark/light
Go Optimizations 101,
Go Details & Tips 101
and Go Generics 101
are all updated for Go 1.24 now.
The most cost-effective way to get them is through this book bundle
in the Leanpub book store.
TapirMD - a powerful, next-generation markup language that simplifies content creation (much more powerful than markdown).
You can experience it online
here.
Does the following Go program compile okay?
package main
const S = "Go"
const G = S[0]
func main() {}
Many gophers might think it should compile okay. But it fails to compile. Because element values of a string are always non-constant in Go, even if the string is a constant.
It is a pity that Go 1.0 didn't specify that elements of constant strings are also constants.
For backward-compatibility, the pity is hard to make up. For example, currently, the following program compiles okay. It prints 185
(-71 + 256).
package main
const S = "Go" // S[0] == 71
func main() {
println(-S[0])
}
But if elements of constant strings become into constants, then the program will not compile, because the type of -S[0]
is byte
(aka. uint8
), whereas -71
owerflows the range of byte
.
It is a pity, it is also a luck.
If elements of constant strings are constants, then there will be parsing ambiguities in Go custom generic age. Since Go 1.18, the following line will be treated as generic type declaration, in which S
is a type parameter and [4]*int
is its constraint.
type T [S [4]*int] struct{}
However, if elements of constant strings are constants, then S [4]
may be treated as constant byte
value if S
is a constant string. In the parsing phase, the compiler doesn't know what the identifier int
denotes. A type or an integer constant? If it denotes an integer constant, and S [4]
may be treated as constant byte
value, then the above line is a valid ordinary array type declaration.
Luckily, now, Go compiler knows S [4]
will never be constant, so it always tries to think the above line is not an ordinary array type declaration. No ambiguities happen here. Were elements of constant strings constants, the simplified type parameter declaration syntax couldn't be possible.
There is
a proposal to let Go support constant arrays (and other constant composite values). However, the Go custom generics design has almost sentenced that proposal to death. Because, similarly, the following code will lead to parsing ambiguities if array values may be declared as constants.
const A = [2]int{1, 2}
type BoolArray [A [1] * int]bool
The following code line doesn't compile in Go:
const _ = "Google"[:2]
Instead, the following line compiles:
var _ = "Google"[:2]
By this fact, the following program will print
128 0
(the reason is explained
here).
package main
const S = "Go"
var a byte = 64 << len(S) / 2
var b byte = 64 << len(S[:]) / 2
func main() {
println(a, b) // 128 0
}
Tapir, the author of Go 101, has been on writing the Go 101 series books
and maintaining the go101.org website since 2016 July.
New contents will be continually added to the book and the website from time to time.
Tapir is also an indie game developer.
You can also support Go 101 by playing
Tapir's games
(made for both Android and iPhone/iPad):
Individual donations via PayPal are also welcome.