Some (Real) Go Subtleties

4 hours ago 1

Go Optimizations 101, Go Details & Tips 101 and Go Generics 101 are all updated for Go 1.25 now. The most cost-effective way to get them is through this book bundle in the Leanpub book store.

I just read an article: 15 Go Subtleties You May Not Already Know. After reading that article, I just feel the title is some weird/improper. Because all the so-called subtleties mentioned in that article are what a quanlified Go programer should know about.

Go indeed has many subtleties. Even many professional Go programmers are not aware of some of them. Here, this article shows several of them (all of them are from the Go Details & Tips 101 book).

For example. What doesn't the following program print? Nothing, true, or false?

package main var a, b [0]int var p, q = &a, &b func main() { if (p == q) { p, q = &a, &b println(p == q) } }

It prints false (with the official Go toolchain). Surprised? But it looks the behavior doesn't violate Go specification.

For example, the function foo shown below compiles, but bar doesn't.

func foo() int { for {} } func bar() int { for true {} }

For example, the following code compiles.

package main var n = -100 func main() { var m = make(map[int]bool, n) m[123] = true; }

A negative cap argument is equivalent to omitting it.

Here is an example to prove it.

package main const s = "zigo 101" // len(s) == 8 var a byte = 1 << len(s) / 128 var b byte = 1 << len(s[:]) / 128 func main() { println(a, b) // 2 0 }

Some Go programmers might be surprised by this result. To understand the result well, we need to know about the next subtlety.

For example, the following program prints 0 0 2.

package main const N = 8 var n = N func main() { var x byte = 1 << n / 128 var y = byte(1 << n / 128) var z byte = 1 << N / 128 println(x, y, z) // 0 0 2 }

In the first two declarations, the types of 1 are both assumed as byte. So the two declarations are both eqivalent to the following line, in which the run-time expression byte(1) << n overflows (and is truncated to 0).

... = byte(1) << n // 128

The last declaration is eqivalent to the following line. The expression 1 << N / 128 is evaluated at compile time. In the expression, 1 is treated as untyped int value.

var z = 2

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.

Read Entire Article