美文网首页码农的世界LinuxGolang
golang cannot assign to XXX 问题分析

golang cannot assign to XXX 问题分析

作者: QxQx | 来源:发表于2019-08-19 22:42 被阅读16次

今天在编译golang项目时,遇到了一个错误。编译器提示 cannot assign to m[1][1]

原项目太大了,不贴了代码大体是这样的

package main

func main() {
    m := make(map[int][2]int)
    a := [2]int{1, 2}
    m[1] = a

    m[1][1] = 3
}

编译器提示,不能取到m[1][1]的地址。
但是使用 fmt 能打印出数值

package main

import "fmt"

func main() {
    m := make(map[int][2]int)
    a := [2]int{1, 2}
    m[1] = a

    // m[1][1] = 3
    fmt.Println(m[1][1])
}

打印结果



想了一下,go中的数组和切片(Slice)的和数组(Array)是不一样的,slice是引用传递,array是值传递。把 a 换成slice试一下
代码如下:

package main

import "fmt"

func main() {
    m := make(map[int][]int)
    a := []int{1, 2}
    m[1] = a

    m[1][1] = 3
    fmt.Println(m[1][1])
}

编译通过,没有问题。

问题找到了,是因为值传递导致的问题,解决办法有三种
1 . 像上面一样,使用slice代替array。
2 . 不直接修改数组的值,修改值时,重新创建数组:

package main

import "fmt"

func main() {
    m := make(map[int][2]int)
    a := [2]int{1, 2}
    m[1] = a
    fmt.Println(m)

    b := [2]int{3, 4}
    m[1] = b
    fmt.Println(m)
}
结果如下:

3 .使用指向数组的指针:

package main

import "fmt"

func main() {
    m := make(map[int]*[2]int)
    a := &[2]int{1, 2}
    m[1] = a
    fmt.Println(m[1])

    m[1][1] = 3
    fmt.Println(m[1])
}

结果如下:



没有问题,可以修改值


在网上搜索没有找到深入点分析的文章,最终在stack overflow中找到了一个挺好的分析传送门
原文:

p["HM"] isn't quite a regular addressable value: hashmaps can grow at runtime, and then their values get moved around in memory, and the old locations become outdated. If values in maps were treated as regular addressable values, those internals of the map implementation would get exposed.
英文比较渣,大体看懂了一点意思。我理解的,应该是在程序执行过程中map的长度会变化,为了map值的正确,go语言不允许直接修改map中的值类型结构。


在想另一种情况:

package main

import "fmt"

func main() {
    m := make(map[int]T)
    t := T{
        One: 1,
        Two: 2,
    }
    m[1] = t
    fmt.Println(m)
    m[1].Two = 3
    fmt.Println(m[1])
}

type T struct {
    One int
    Two int
}

运行:



编译器提示同样的错误
换成指针后:

package main

import "fmt"

func main() {
    m := make(map[int]*T)
    t := &T{
        One: 1,
        Two: 2,
    }
    m[1] = t
    fmt.Println(m[1])
    m[1].Two = 3
    fmt.Println(m[1])
}

type T struct {
    One int
    Two int
}

运行:



先总结到这把,996确实有点累。早睡早起多搬砖

相关文章

网友评论

    本文标题:golang cannot assign to XXX 问题分析

    本文链接:https://www.haomeiwen.com/subject/nhcysctx.html