Golang cannot assign to arrays inside maps

打倒美帝 · · 794 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

问题描述

今天在运行golang程序时出现编译错误cannot assign to infoMap[osd.OsdID][0]。大致和参考链接中的例子类似:

package main

import "fmt"

func main() {
    array := [3]int{1, 2, 3}
    array[0]++ // Works
    slice := make([]int, 3)
    for i := range slice {
        slice[i] = i + 1
    }
    arrayMap := make(map[int][3]int)
    sliceMap := make(map[int][]int)
    arrayMap[0] = array
    sliceMap[0] = slice
    //arrayMap[0][0]++ // Does not compile: "cannot assign to arrayMap[0][0]"
    sliceMap[0][0]++
    fmt.Println(arrayMap)
    fmt.Println(sliceMap)
}

编译时arrayMap[0][0]++会出现cannot assign to arrayMap[0][0]的错误。

分析

Assignments: "Each left-hand side operand must be addressable, a map index expression, or (for = assignments only) the blank identifier."
Address operators: "The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array."

Go's arrays are values. An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents. (To avoid the copy you could pass a pointer to the array, but then that's a pointer to an array, not an array.) One way to think about arrays is as a sort of struct but with indexed rather than named fields: a fixed-size composite value.
Slices are pass by reference, while arrays are pass by value.

当数组被放置在map中时,其实是数组的拷贝,而且当你在map外面使用时也是做了一次拷贝,因此修改数组时并不是真正对原始的数组进行了修改,由于arrayMap[0]不是an array indexing operation of an addressable array,所以编译不通过。

sliceMap[0][0]++类似于:

arr := sliceMap[0]
arr[0] = arr[0] + 1

arr实际是sliceMap[0]数据的一份拷贝。

借用参考链接Playground中的例子来说明:

package main

import "fmt"
import "reflect"

func checkArrays() {
    array := [3]int{1, 2, 3}
    arrayMap := map[int][3]int{
        0: array,
    }
    arr := arrayMap[0]
    fmt.Println(reflect.DeepEqual(arr, array))
    arr[0]++
    fmt.Println(reflect.DeepEqual(arr, array))
}

func checkSlices() {
    slice := []int{1, 2, 3}
    sliceMap := map[int][]int{
        0: slice,
    }
    slc := sliceMap[0]
    fmt.Println(reflect.DeepEqual(slc, slice))
    slc[0]++
    fmt.Println(reflect.DeepEqual(slc, slice))

}

func main() {
    checkArrays()
    checkSlices()
}

输出结果为:

true
false
true
true

从结果可以看出arrarrayMap[0]的一份拷贝,修改arr的值不会对arrayMap[0]有影响。而slcsliceMap[0]共享底层数据,修改时其实是修改的同一份数据。

References


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:打倒美帝

查看原文:Golang cannot assign to arrays inside maps

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

794 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传