【问题标题】:Why can't I initialize a map with new() in Go?为什么我不能在 Go 中使用 new() 初始化地图?
【发布时间】:2018-12-16 13:37:37
【问题描述】:
package main

import "fmt"

func main() {
    p := new(map[string]int)
    m := make(map[string]int)
    m["in m"] = 2
    (*p)["in p"] = 1
    fmt.Println(m)
    fmt.Println(*p)
}

上面的代码给出了一个错误panic: assignment to entry in nil map。如果我在将对插入其中之前打印*p,则输出是正确的。看来我就是不能修改*p

【问题讨论】:

    标签: dictionary go


    【解决方案1】:

    newmake 都用于在程序中分配内存,但它们的工作方式不同。 new(T, args) 将内存归零并返回内存地址(*T 类型的值)但不初始化该内存。另一方面,make(T, args) 初始化 T 类型的值。地图需要初始化,因为虽然地图可以为空,但地图本身的结构仍然是非零的,因此需要在使用前进行初始化。

    来自Effective Go

    内置函数 make(T, args) 的用途与 new(T) 不同。它只创建切片、映射和通道,并返回 T 类型(不是 *T)的初始化(非归零)值。区别的原因是这三种类型在幕后代表了对必须在使用前初始化的数据结构的引用。例如,切片是一个包含指向数据(在数组内部)、长度和容量的指针的三项描述符,在这些项被初始化之前,切片为 nil。对于切片、映射和通道,make 初始化内部数据结构并准备使用值。

    【讨论】:

    • 这是否意味着我们永远不应该尝试使用 new() 来初始化地图?
    • @Einiemand 如果您想创建 地图,请使用 make 函数。如果你想分配一个映射变量设置为nil,那么使用新函数。新函数不会创建地图。
    • @Einiemand 我同意上述评论。在这个示例中,可能是大多数示例中,您需要使用 make 函数。
    【解决方案2】:

    这不是new 关键字的直接问题。如果你没有初始化你的地图,当你用 var 关键字声明它时,你会得到相同的行为,例如:

    var a map[string]int
    a["z"] = 10
    

    解决这个问题的方法是初始化地图:

    var a map[string]int
    a = map[string]int{}
    a["z"] = 10
    

    它的工作方式相同,使用 new 关键字:

    p := new(map[string]int)
    *p = map[string]int{}
    (*p)["in p"] = 1 
    

    make(map[string]int) 做你所期望的原因是地图被声明和初始化。

    Go Playground

    【讨论】:

      猜你喜欢
      • 2010-12-16
      • 1970-01-01
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多