为什么在golang中打印一个(nil)映射会产生非"<nil>"的结果?

6
在golang中,如果您创建了一个包含未初始化的映射的结构体,则打印该映射会产生一个非<nil>字符串。
为什么空映射的“print”输出“map[]”,而不是<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))

4
这只是格式化程序的输出方式。这样做只是为了方便,因此显示类型很有用(更不用说你可以从nil映射中进行索引)。 - JimB
@JimB 那其实就是答案,发表出来吧。 - icza
2个回答

6

这只是为了清晰明了。如果你运行这段代码:

var m map[string]int64
log.Println(m == nil)
log.Printf("%T\n", m)

它将会打印出:
$ true
$ map[string]int64

所以此时m实际上是nil。一个nil值也可以有类型,并且格式化器在可能的情况下使用它来打印出有意义的内容。

map在其他语言中的行为类似于引用类型。在Go中,即使结构体的值为nil,您也可以调用其方法。

因此,对于您自己的结构体,您只需定义String() string方法即可实现fmt.Stringer接口,并在您的结构体的值为nil时打印出比<nil>更合适的内容。示例如下:

type someData struct {
    someValue string
}

func (x *someData) String() string {
    if x == nil {
        return "NO PROPER DATA HERE!"
    }

    return x.someValue
}

如果我们运行:

var data *someData
log.Println(data)
data = new(someData)
data.someValue = "Aloha! :)"
log.Println(data)

输出结果将是:
$ NO PROPER DATA HERE!
$ Aloha! :)

看第一行,尽管我们的结构体指针此时是nil,但我们没有得到<nil>作为输出。


0

一个空指针不同于一个空(或零)映射。有关零值的权威信息,请参见https://golang.org/ref/spec#The_zero_value

如果您想要一个空指针,您需要一个指针,例如以下示例

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)
}

这将会得到:

myMap before assignment: map[]
myMap after assignment : map[]
myMapPointer before assignment: <nil>
myMapPointer after assignment : &map[]

除非你引用的文档明确说明映射的零值为 nil,否则不然。https://play.golang.org/p/c6NOfiotCC - JimB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接