今天在編譯golang項(xiàng)目時(shí),遇到了一個(gè)錯(cuò)誤攘残。編譯器提示 cannot assign to m[1][1]
原項(xiàng)目太大了离赫,不貼了代碼大體是這樣的
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 能打印出數(shù)值
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])
}
打印結(jié)果
想了一下禾乘,go中的數(shù)組和切片(Slice)的和數(shù)組(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])
}
編譯通過,沒有問題彼宠。
問題找到了鳄虱,是因?yàn)橹祩鬟f導(dǎo)致的問題,解決辦法有三種
1 . 像上面一樣凭峡,使用slice代替array拙已。
2 . 不直接修改數(shù)組的值,修改值時(shí)摧冀,重新創(chuàng)建數(shù)組:
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)
}
結(jié)果如下:3 .使用指向數(shù)組的指針:
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])
}
結(jié)果如下:
沒有問題倍踪,可以修改值
在網(wǎng)上搜索沒有找到深入點(diǎn)分析的文章系宫,最終在stack overflow中找到了一個(gè)挺好的分析傳送門
原文:
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 themap
implementation would get exposed.
英文比較渣,大體看懂了一點(diǎn)意思建车。我理解的扩借,應(yīng)該是在程序執(zhí)行過程中map的長度會(huì)變化,為了map值的正確缤至,go語言不允許直接修改map中的值類型結(jié)構(gòu)潮罪。
在想另一種情況:
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
}
運(yùn)行:
編譯器提示同樣的錯(cuò)誤
換成指針后:
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
}
運(yùn)行: