为什么在Go语言中打印一个空的map时,结果不是”“?

huangapple go评论81阅读模式
英文:

Why does printing of a (nil) map in golang yield a non "<nil>" result?

问题

在Golang中,如果你创建了一个包含未初始化的映射的结构体,并打印该映射,输出的字符串将不是<nil>,而是map[]

为什么打印一个空映射的结果是map[]而不是<nil>

假设上面有一个结构体a,其中包含一个名为AA的映射,该映射已创建但未初始化。

输出结果为:

map[]
map[]

这是因为在Golang中,未初始化的映射被认为是一个空映射,而不是nil。当你打印一个未初始化的映射时,它会显示为map[],表示一个空映射。要创建一个nil映射,你需要使用var关键字声明映射变量,并将其初始化为nil。例如:

var m map[string]int
fmt.Println(m) // 输出: map[]

希望能帮到你!如果还有其他问题,请随时提问。

英文:

In golang, if you create a struct with a map in it, which is uninitialized, printing the map yields a non &lt;nil&gt; string.

Why does "print" of a nil map output "map[]" instead of &lt;nil&gt; ?

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

答案1

得分: 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> 作为输出。

英文:

It's just for making things clear. If you run this code:

var m map[string]int64
log.Println(m == nil)
log.Printf(&quot;%T\n&quot;, 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 &lt;nil&gt;. Having:

type someData struct {
	someValue string
}

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

	return x.someValue
}

Then if we run:

var data *someData
log.Println(data)
data = new(someData)
data.someValue = &quot;Aloha! :)&quot;
log.Println(data)

The output will be:

$ NO PROPER DATA HERE!
$ Aloha! :)

See at the first line we did not get &lt;nil&gt; as output, despite the fact that our struct pointer is nil at that point.

答案2

得分: 0

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

如果你想要一个空指针,你需要一个指针,就像下面的示例中所示:

package main

import (
	"fmt"
)

func main() {
	var myMap map[string]int64
	fmt.Printf("myMap赋值前:%v\n", myMap)

	myMap = make(map[string]int64)
	fmt.Printf("myMap赋值后:%v\n", myMap)

	var myMapPointer *map[string]int64
	fmt.Printf("myMapPointer赋值前:%v\n", myMapPointer)

	myMapPointer = new(map[string]int64)
	fmt.Printf("myMapPointer赋值后:%v\n", myMapPointer)
}

运行结果为:

myMap赋值前:map[]
myMap赋值后:map[]
myMapPointer赋值前:nil
myMapPointer赋值后:&map[]
英文:

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:

<!-- language: go -->

package main

import (
    &quot;fmt&quot;
)

func main() {
    var myMap map[string]int64
    fmt.Printf(&quot;myMap before assignment: %v\n&quot;, myMap)

    myMap = make(map[string]int64)
    fmt.Printf(&quot;myMap after assignment : %v\n&quot;, myMap)

    var myMapPointer *map[string]int64
    fmt.Printf(&quot;myMapPointer before assignment: %v\n&quot;, myMapPointer)

    myMapPointer = new(map[string]int64)
    fmt.Printf(&quot;myMapPointer after assignment : %v\n&quot;, myMapPointer)
}

This gives:

myMap before assignment: map[]
myMap after assignment : map[]
myMapPointer before assignment: &lt;nil&gt;
myMapPointer after assignment : &amp;map[]

huangapple
  • 本文由 发表于 2016年12月12日 03:01:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/41089913.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定