Go的新手。遇到这个错误,没有找到原因或理由:
如果我创建一个结构体,我显然可以分配和重新赋值,没问题:
type Person struct {
name string
age int
}
func main() {
x := Person{"Andy Capp", 98}
x.age = 99
fmt.Printf("age: %d\n", x.age)
}
但如果结构是地图中的一个值:
type Person struct {
name string
age int
}
type People map[string]Person
func main() {
p := make(People)
p["HM"] = Person{"Hank McNamara", 39}
p["HM"].age = p["HM"].age + 1
fmt.Printf("age: %d\n", p["HM"].age)
}
我得到cannot assign to p["HM"].age
。这就是它,没有其他信息。 http://play.golang.org/p/VRlSItd4eP
我找到了解决这个问题的方法 - 在Person上创建一个incrementAge
func,可以调用它并将结果分配给地图键,例如p["HM"] = p["HM"].incrementAge()
。
但是,我的问题是,这是什么原因"无法分配"错误,为什么不允许我直接分配结构值?
答案 0 :(得分:77)
p["HM"]
不是常规addressable值:hashmaps can grow at runtime,然后他们的值会在内存中移动,旧位置会过时。如果映射中的值被视为常规可寻址值,则map
实现的内部结构将被暴露。
所以,相反,p["HM"]
是一个稍微不同的东西,称为"地图index expression"在规范中;如果您在规范中搜索短语"索引表达式"你会发现你可以用它们做某些事情,比如读它们,分配给它们,并在递增/递减表达式中使用它们(对于数字类型)。但你不能做任何事情。他们本可以选择实施更多特殊情况,但我猜他们并不只是为了让事情变得简单。
您的方法在这里似乎很好 - 您将其更改为常规分配,这是一项特别允许的操作。另一种方法(对于你想避免复制的大型结构可能有用吗?)是make the map value a regular old pointer你可以通过以下方式修改底层对象:
package main
import "fmt"
type Person struct {
name string
age int
}
type People map[string]*Person
func main() {
p := make(People)
p["HM"] = &Person{"Hank McNamara", 39}
p["HM"].age += 1
fmt.Printf("age: %d\n", p["HM"].age)
}
答案 1 :(得分:2)
作业的左侧必须是“可寻址的”。
https://golang.org/ref/spec#Assignments
每个左侧操作数必须是可寻址的,一个映射索引表达式,或者(仅用于=赋值)空白标识符。
和https://golang.org/ref/spec#Address_operators
操作数必须是可寻址的,即,变量,指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。
作为@ twotwotwo的评论,p["HM"]
无法解决。
但是,没有这样的定义表明sepc中的“可寻址结构操作数”是什么。我认为他们应该为它添加一些描述。