Reputation: 17648
In golang, if you create a struct with a map in it, which is uninitialized, printing the map yields a non <nil>
string.
Why does "print" of a nil map output "map[]" instead of <nil>
?
// Assume above there is a struct, a.AA, which is created but which otherwise
// has not created the map.
//output:
//map[]
//map[]
fmt.Println(a.AA)
fmt.Println(make(map[string]int64))
Upvotes: 6
Views: 2163
Reputation: 13523
It's just for making things clear. If you run this code:
var m map[string]int64
log.Println(m == nil)
log.Printf("%T\n", m)
It will print:
$ true
$ map[string]int64
So m
is actually nil
at this point. A nil
value (can) have a type too and the formater uses that to print out something meaningful when possible.
A map
behaves like a reference type in other languages. And in Go you can call methods of a struct even if its value is nil
.
So even for your own structs, you can implement fmt.Stringer
interface by just defining the String() string
method on your struct and whenever your struct's value is nil
you can print out something more proper than <nil>
. Having:
type someData struct {
someValue string
}
func (x *someData) String() string {
if x == nil {
return "NO PROPER DATA HERE!"
}
return x.someValue
}
Then if we run:
var data *someData
log.Println(data)
data = new(someData)
data.someValue = "Aloha! :)"
log.Println(data)
The output will be:
$ NO PROPER DATA HERE!
$ Aloha! :)
See at the first line we did not get <nil>
as output, despite the fact that our struct pointer is nil
at that point.
Upvotes: 6
Reputation: 659
A nil pointer is not the same as an empty (or zero) map. See https://golang.org/ref/spec#The_zero_value for authoritative information concerning zero values.
If you want a nil, you need a pointer, such as in the following example:
package main
import (
"fmt"
)
func main() {
var myMap map[string]int64
fmt.Printf("myMap before assignment: %v\n", myMap)
myMap = make(map[string]int64)
fmt.Printf("myMap after assignment : %v\n", myMap)
var myMapPointer *map[string]int64
fmt.Printf("myMapPointer before assignment: %v\n", myMapPointer)
myMapPointer = new(map[string]int64)
fmt.Printf("myMapPointer after assignment : %v\n", myMapPointer)
}
This gives:
myMap before assignment: map[]
myMap after assignment : map[]
myMapPointer before assignment: <nil>
myMapPointer after assignment : &map[]
Upvotes: 0