Gopher Puzzlers
How well do you know your language?
12 December 2019
Dave Cheney
Dave Cheney
Hopefully this little quiz will surprise you, and perhaps teach you something you didn't know about Go.
3
Here are the rules
Consider this program
package main import "fmt" var x int func init() { main() } func main() { x++ fmt.Println(x) }
Credit: Damian Gryski
What does this program print?
5Consider this program
package main import ( "fmt" ) func main() { i := []int{ 1, 2, 3, } for j := range i { fmt.Println(j) } }
What does this program print?
6Consider this program
package main import ( "fmt" ) func main() { s := make([]int, 3, 8) s[2:5][0] = 5 fmt.Println(s) }
What does this program print?
7Consider this program
package main import "fmt" func main() { false := true fmt.Println(true == false == true) }
What does this program print?
8Consider this program
package main import ( "fmt" ) func main() { var err error _, true := err.(error) fmt.Println(true) }
What does this program print?
9
true and false are not keywords, they are predeclared identifiers.
true and false are declared at the universe block, a block that encompases all Go source.
Consider this program
package main import "fmt" func main() { true := 6 fmt.Println(true > false) }
What does this program print?
11Consider this program
package main import "fmt" func main() { s := make([]int, 0, 8) fmt.Println(len(s)) }
What does this program print?
12Consider this program
package main import "fmt" func main() { s := make([]int, 0, 8) r := s[2:6:7] fmt.Println(len(r), cap(r)) }
What does this program print?
13
s is a []int slice.
The length of s is 0, the capacity of s is 8.
Any slice can be resliced to make it smaller and larger, up to its capacity.
However, the three arg slice operation permits the caller to specify the maximum capacity of a slice.
Thus r is a []int slice of length 4 and capacity 5.
Consider this program
package main import "fmt" var i = 2 func main() { j := 2 * 2i fmt.Println(j) }
What does this program print?
15Consider this program
package main import ( "fmt" ) const ( c1 int = iota c2 c3 c4 rune = iota c5 ) func main() { fmt.Println(c5) }
What does this program print?
16Consider this program
package main import "fmt" func main() { s := string("touché") b := []byte{'t', 'o', 'u', 'c', 'h', 'é'} fmt.Println(len(s) == len(b)) }
true or false?Does this program compile?
package main import "fmt" func main() { m := make(map[string]int) m["foo"]++ fmt.Println(m["foo"]) }
If it does, what does it print?
18Yes, it does compile.
Here is the same program rewritten to be more explicit.
package main import "fmt" func main() { m := make(map[string]int) v := m["foo"] v++ m["foo"] = v fmt.Println(m["foo"]) }
Consider this program
package main import "fmt" const ( Animal = iota Mineral Vegetable ) func genus(t uint) { switch t { case Animal: fmt.Println("Animal") case Mineral: fmt.Println("Mineral") case Vegetable: fmt.Println("Vegetable") } } func main() { genus(-Animal) }
Consider this program
package main import "fmt" var x = 1 func a() int { x *= 2 return x } func b() int { x /= 2 return x } func sub(a, b int) int { return a - b } func main() { fmt.Println(sub(a(), b())) }
What does it print?
Consider this program
package main import "time" func main() { t := time.NewTicker(100) for range t.C { t.Stop() } }
Does it
Stop turns off a ticker. After Stop, no more ticks will be sent. Stop does not close the channel, to prevent a read from the channel succeeding incorrectly.
package main
import (
"fmt"
"time"
)
func main() { t := time.NewTicker(100) t.Stop() for { select { case <-t.C: fmt.Println("tick") } } }
Consider this program
package main import "fmt" func main() { var x uint32 = 100.5 + 100.5 + 2147483447.0 fmt.Println(x) }
Does it compile?
24Although Go does not permit implicit conversion between variables, the rules are different for constants.
Specifically:
A constant value x can be converted to type T in any of these cases:
x is representable by a value of type T.What does this program print?
package main import ( "fmt" "strings" ) func main() { s := strings.TrimRight("abcdefedcba", "abcdef") fmt.Printf("%q\n", s) }
"abcdef""fedcba""""abcedfedcba"
strings.TrimRight takes a cutset for their second argument.
If the rightmost character is a member of the cutset, it is removed, and we go again, otherwise stop.
strings.Trim{,Left,Right} are great for trimming a set of characters (usually whitespace), from a string, but if you know the prefix or suffix, you probably want strings.Trim{Prefix,Suffix}
package main import ( "fmt" "strings" ) func main() { s := strings.TrimSuffix("abcdefedcba", "abcdef") fmt.Printf("%q\n", s) }
Will this program terminate?
package main import "fmt" func main() { v := []int{1, 2, 3} for i := range v { v = append(v, i) } fmt.Println(v) }
The for ... range syntax only evaluates the terminating condition once, at the start of the loop.
package main import "fmt" func main() { v := []int{1, 2, 3} for i, n := 0, len(v); i < n; i++ { v = append(v, i) } fmt.Println(v) }
Take Away: if you are modifying a slice while iterating over it; use a regular for loop.
What does this code print
package main import "fmt" func main() { r := []rune("☃") fmt.Println(r) }
[9731]
rune is an alias for int32.
package main import ( "fmt" ) func main() { var r rune fmt.Printf("%T\n", r) }
What does this program print?
Question: How many other predeclared aliases are there? What are their names?
31Which of these declarations are valid?
package main import "fmt" func main() { b := []byte("Hello") r := []rune("Sydney") i := []int("Gophers") fmt.Println(b, r, i) }
Consider this program
package main import "fmt" func main() { fmt.Println(len(map[interface{}]int{ new(int): 1, new(int): 2, new(struct{}): 3, new(struct{}): 4, })) }
Credit: Brad Fitzpatrick
Spec: Size and alignment guarantees:
"A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory."
package main import "fmt" func main() { p, q := new(int), new(int) fmt.Println(*p == *q, p == q) r, s := new(struct{}), new(struct{}) fmt.Println(*r == *s, r == s) }
package main import "fmt" var ( p, q = new(int), new(int) r, s = new(struct{}), new(struct{}) ) func main() { fmt.Println(*p == *q, p == q) fmt.Println(*r == *s, r == s) }
Does this code compile?
package main type bar0 struct { n * bar0 m []bar0 } func main() { }
Credit: fuuucl.am on golang-dev.
36Yes, it does compile.
If it did not, you would not be able to write
package main
import "fmt"
func main() {
x := 1 * 2 * 3 fmt.Println(x)
}
When the input is broken into tokens, a semicolon is automatically inserted into the token stream immediately after a line's final token if that token is
golang.org/ref/spec#Semicolons
37