相关问题在这里https://stackoverflow.com/a/12965872/6421681。在 go 中,您可以执行以下操作:func numsInFactorial(n int) (nums []int) { // `nums := make([]int)` is not needed for i := 1; i <= n; i++ { nums = append(nums, i) } return}但是,以下内容不起作用:func mapWithOneKeyAndValue(k int, v int) (m map[int]int) { m[k] = v return}抛出一个错误:panic: assignment to entry in nil map相反,您必须:func mapWithOneKeyAndValue(k int, v int) map[int]int { m := make(map[int]int) m[k] = v return}我找不到此行为的文档。我已经通读了 effective go 的所有内容,那里也没有提到它。我知道命名的返回值是定义的(即内存已分配;接近所做的new)但未初始化(因此make不会复制行为)。经过一些实验,我相信这种行为可以简化为理解以下代码的行为:func main() { var s []int // len and cap are both 0 var m map[int]int fmt.Println(s) // works... prints an empty slice fmt.Println(m) // works... prints an empty map s = append(s, 10) // returns a new slice, so underlying array gets allocated fmt.Println(s) // works... prints [10] m[10] = 10 // program crashes, with "assignment to entry in nil map" fmt.Println(m)}这个问题似乎append很可能调用make并分配一个新的切片来检测容量s是0. 但是,map永远不会得到显式初始化。这个 SO 问题的原因有两个。首先,我想记录下 SO 上的行为。slice其次,为什么该语言允许和的非初始化定义map?根据我到目前为止的经验,它似乎是一种实用的语言(即未使用的变量导致编译失败,gofmt 强制正确格式化),因此阻止代码编译是有意义的。
2 回答
繁华开满天机
TA贡献1816条经验 获得超4个赞
尝试按索引分配 nil 切片 - 你会得到“恐慌:运行时错误:索引超出范围”
append 函数与 nil 一起工作的唯一原因是 append 函数可以对给定的切片进行重新分配。例如,如果您尝试将第 6 个元素附加到当前容量为 5 的 5 个元素的切片,它将创建具有新容量的新数组,从旧数组复制所有信息,并交换给定切片中的数据数组指针。在我的理解中,它只是动态数组的 golang 实现。
因此,nil slice 只是容量不足的 slice 的特例,因此它会在任何追加操作时重新分配。
慕斯王
TA贡献1864条经验 获得超2个赞
一个 nil 映射在读取时表现得像一个空映射,但尝试写入一个 nil 映射会导致运行时恐慌;不要那样做。要初始化地图,请使用内置的 make 函数
似乎 nil 映射被认为是有效的空映射,这就是他们不为其自动分配内存的原因。
- 2 回答
- 0 关注
- 117 浏览
添加回答
举报
0/150
提交
取消