问题描述
新手.遇到了这个错误,但没有找到原因或理由:
New to Go. Encountered this error and have had no luck finding the cause or the rationale for it:
如果我创建一个结构体,我显然可以毫无问题地分配和重新分配值:
If I create a struct, I can obviously assign and re-assign the values no problem:
type Person struct {
name string
age int
}
func main() {
x := Person{"Andy Capp", 98}
x.age = 99
fmt.Printf("age: %d
", x.age)
}
但是如果结构体是映射中的一个值:
but if the struct is one value in a map:
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
", p["HM"].age)
}
我得到 无法分配给 p["HM"].age
.就是这样,没有其他信息.http://play.golang.org/p/VRlSItd4eP
I get cannot assign to p["HM"].age
. That's it, no other info. http://play.golang.org/p/VRlSItd4eP
我找到了解决这个问题的方法 - 在 Person 上创建一个 incrementAge
函数,可以调用它并将结果分配给映射键,例如 p["HM"] = p["HM"].incrementAge()
.
I found a way around this - creating an incrementAge
func on Person, which can be called and the result assigned to the map key, eg p["HM"] = p["HM"].incrementAge()
.
但是,我的问题是,这个无法分配"错误的原因是什么,为什么不允许我直接分配结构值?
But, my question is, what is the reason for this "cannot assign" error, and why shouldn't I be allowed to assign the struct value directly?
推荐答案
p["HM"]
不是一个普通的 addressable 值:hashmap 可以在运行时增长,然后它们的值在内存中移动,旧位置变得过时.如果映射中的值被视为常规的可寻址值,那么 map
实现的内部结构就会暴露出来.
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.
因此,p["HM"]
是一个稍微不同的东西,称为地图 索引表达式";如果您在规范中搜索短语索引表达式",您会发现您可以用它们做某些事情,例如读取它们,分配给它们,并在增量/减量表达式中使用它们(对于数字类型).但你不能做所有事情.他们本可以选择实施更多的特殊情况,但我猜他们不仅仅是为了让事情变得简单.
So, instead, p["HM"]
is a slightly different thing called a "map index expression" in the spec; if you search the spec for the phrase "index expression" you'll see you can do certain things with them, like read them, assign to them, and use them in increment/decrement expressions (for numeric types). But you can't do everything. They could have chosen to implement more special cases than they did, but I'm guessing they didn't just to keep things simple.
您的方法在这里看起来不错——您将其更改为常规分配,这是特别允许的操作之一.另一种方法(可能适用于您想要避免复制的大型结构?)是 使地图值成为常规的旧指针,您可以通过以下方式修改底层对象:
Your approach seems good here--you change it to a regular assignment, one of the specifically-allowed operations. Another approach (maybe good for larger structs you want to avoid copying around?) is to make the map value a regular old pointer that you can modify the underlying object through:
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
", p["HM"].age)
}
这篇关于为什么我会收到“无法分配"的消息?将值设置为结构作为映射中的值时出错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!