8

有类型 Company,它是一个结构,包含 Person 的映射,它们也是所有结构。

type Company struct {
    employees map[int]Person
}

type Person struct {
    [...]
}

在将一些人分配给员工地图之后,我试图在每个人上调用一个指针方法。

func (company *Company) Populate(names []string) {
    for i := 1; i <= 15; i++ {
        company.employees[i] = Person{names[i - 1], [...]}
        company.employees[i].Initialize()
    }
}

这悲惨地失败了,go-Compiler 抱怨我无法在company.employees[i]上调用指针方法,也无法获取company.employees[i]的地址。但是,将 Initialize-method 设置为非指针方法并让它返回 person 的副本,并通过使用再次将其分配给地图

company.employees[i] = company.employees[i].Initialize()

工作,这并没有什么不同。

从来没有使用过指针,这让我非常恼火。地图不是一成不变的,它们会以任何一种方式进行修改,因此在地图中的实体上调用指针方法应该不是问题——至少在我的脑海中是这样。

如果有人可以向我解释我在这里做错了什么 - 或者纠正我的想法 - 我会很高兴。

4

2 回答 2

15

这里的问题是,为了调用指针方法,employees[i]需要获取的地址。根据Go 规范

操作数必须是可寻址的,即变量、指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。作为可寻址性要求的一个例外,x 也可以是复合文字。

地图索引操作是不可寻址的。这是为了地图实现不需要保证值的地址不会改变。随着更多数据添加到地图中,出于效率原因,它可能会重新定位数据。

那么,您该如何解决呢?如果您有map[int]*Person,则无需获取地图中数据的地址,因为地图值已经是地址。

最后一点建议,Person.Initialize()不是非常惯用的 Go 代码。如果需要初始化类型,通常使用NewPerson()函数。该NewPerson()函数将返回一个初始化的 Person 结构或指针。

于 2012-10-27T15:41:21.303 回答
0

例如,

package main

import "fmt"

type Person struct {
    Name string
}

func NewPerson(name string) *Person {
    return &Person{Name: name}
}

type Company struct {
    Employees map[int]*Person
}

func (c *Company) Populate(names []string) {
    c.Employees = make(map[int]*Person)
    for i := range names {
        c.Employees[i+1] = NewPerson(names[i])
    }
}

func main() {
    c := Company{}
    c.Populate([]string{"Peter", "Paul"})
    for k, v := range c.Employees {
        fmt.Println(k, *v)
    }
}

输出:

1 {Peter}
2 {Paul}
于 2012-10-27T15:21:40.737 回答