“nil slice” vs “nil map”


Slice and map are all reference types in Go, and their default values are nil:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var (
  5. s []int
  6. m map[int]bool
  7. )
  8. if s == nil {
  9. fmt.Println("The value of s is nil")
  10. }
  11. if m == nil {
  12. fmt.Println("The value of m is nil")
  13. }
  14. }

The result is like this:

  1. The value of s is nil
  2. The value of m is nil

When a slice’s value is nil, you could also do operations on it, such as append:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var s []int
  5. fmt.Println("Is s a nil? ", s == nil)
  6. s = append(s, 1)
  7. fmt.Println("Is s a nil? ", s == nil)
  8. fmt.Println(s)
  9. }

The result is like this:

  1. Is s a nil? true
  2. Is s a nil? false
  3. [1]

A caveat you should notice is the length of both nil and empty slice is 0:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var s1 []int
  5. s2 := []int{}
  6. fmt.Println("Is s1 a nil? ", s1 == nil)
  7. fmt.Println("Length of s1 is: ", len(s1))
  8. fmt.Println("Is s2 a nil? ", s2 == nil)
  9. fmt.Println("Length of s2 is: ", len(s2))
  10. }

The result is like this:

  1. Is s1 a nil? true
  2. Length of s1 is: 0
  3. Is s2 a nil? false
  4. Length of s2 is: 0

So you should compare the slice’s value with nil to check whether it is a nil.

Accessing a nil map is OK, but storing a nil map cause program panic:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var m map[int]bool
  5. fmt.Println("Is m a nil? ", m == nil)
  6. fmt.Println("m[1] is ", m[1])
  7. m[1] = true
  8. }

The result is like this:

  1. Is m a nil? true
  2. m[1] is false
  3. panic: assignment to entry in nil map
  4. goroutine 1 [running]:
  5. panic(0x4cc0e0, 0xc082034210)
  6. C:/Go/src/runtime/panic.go:481 +0x3f4
  7. main.main()
  8. C:/Work/gocode/src/Hello.go:9 +0x2ee
  9. exit status 2
  10. Process finished with exit code 1

So the best practice is to initialize a map before using it, like this:

  1. m := make(map[int]bool)

BTW, you should use the following pattern to check whether there is an element in map or not:

  1. if v, ok := m[1]; !ok {
  2. .....
  3. }

Reference:
The Go Programming Language.