A Quiz of Equal Operator in Go

Yinchi Luo
4 min readDec 29, 2020
When was the last time you took a quiz? Photo by Jason Sung on Unsplash

Here is a quiz of == (equal operator) in Go, if you pass all of them, you could skip this article. Otherwise, you may want to check the explanation below.

Quiz

Assume the statements of every quiz is inside of a separate function body. For brevity, I will skip the function signature.

// 1
a := []int{1, 2, 3}
b := []int{1, 2, 3}
fmt.Println(a == b)
// 2
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
fmt.Println(a == b)
// 3
a := [4]int{1, 2, 3}
b := [4]int{1, 2, 3}
fmt.Println(a == b)
// 4
a := map[string]bool{"go": true}
b := map[string]bool{"go": true}
fmt.Println(a == b)
// 5
a := func(n int) bool { return n%2 == 0 }
b := func(n int) bool { return n%2 == 0 }
fmt.Println(a == b)
// 6
a := []int{1, 2, 3}
b := []int{1, 2, 3}
fmt.Println(&a == &b)

Answers

1
Failed to build
invalid operation: a == b (slice can only be compared to nil)
2
true
3
true
4
Failed to build
invalid operation: a == b (map can only be compared to nil)
5
Failed to build
invalid operation: a == b (func can only be compared to nil)
6
false

Explanation

Slice literal and array literal

In Quiz 1 []int{1, 2, 3} is a slice literal , whereas in Quiz 2, we have an array literal [3]int{1, 2, 3}.

Thus, a and b in Quiz 1 has type Slice, while a and b in Quiz 2 has type Array .

If you are not familiar with slice, and wonder how it is related to array, you can check this blog post: https://blog.golang.org/slices.

The length of an array literal is the length specified in the literal type. If fewer elements than the length are provided in the literal, the missing elements are set to the zero value for the array element type.

buffer := [10]string{} // len(buffer) == 10

intSet := [6]int{1, 2, 3, 5} // len(intSet) == 6]

days := [...]string{"Sat", "Sun"} // len(days) == 2

(…)

A slice literal has the form

[]T{x1, x2, … xn}

and is shorthand for a slice operation applied to an array:

tmp := [n]T{x1, x2, … xn}

tmp[0 : n]

— The Go Programming Language Specification

Since the missing element in array literal are set to the zero value of the corresponding element type, we know in Quiz 3, [4]int{1, 2, 3} will yield an array [1, 2, 3, 0], since zero value of int is 0 .

Array values are comparable if values of the array element type are comparable. Two array values are equal if their corresponding elements are equal.

The Go Programming Language Specification

Now we know why Quiz 2 and Quiz 3 both have answer true, since in those two scenarios, both a and b are array of integer and they contains the same elements.

Slice, map and function value can only compare to nil

Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.

— The Go Programming Language Specification

This explains why Quiz 1, 4, 5 is failed to build.

If you want to know more about function value, you could check my previous article: Write a Nested Recursive Function in Go.

By the way, don’t ever try to fool the compiler by converting uncomparable values to interface{} :

a := []int{1, 2, 3}
b := []int{1, 2, 3}
ai := interface{}(a)
bi := interface{}(b)
fmt.Println(ai == bi)

This will panic in the runtime:

$ go run main.go
panic: runtime error: comparing uncomparable type []int

A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable. This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.

The Go Programming Language Specification

Keep in mind, compiler is your friend not your enemy.

Pointer values are comparable

Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil.

The Go Programming Language Specification

This explains why Quiz 6 is succeeded to build but yield false .

By the way, comparison of pointers to zero-size variables is not guaranteed to yield true :

Pointers to distinct zero-size variables may or may not be equal.

The Go Programming Language Specification

Two distinct zero-size variables may have the same address in memory.

The Go Programming Language Specification

So you should check the underlying variables instead if you think the pointers you compare could point to zero-size variables.

Conclusion

I hope you have learned a little bit more about Go through this quiz.

Who know there are so many stuffs behind, even though this only touch a tip of the equal operator. I plan to write a separate article to investigate the equality for user-defined data structure. Stay tuned.

Thank you for reading and stay safe :)

Reference

The Go Programming Language Specification

--

--

Yinchi Luo

Cloud native & remote native, Senior Software Engineer @ Instana