我有以下代码
http://play.golang.org/p/d-bZxL72az
package main
import "fmt"
type Variables struct {
sum uint64
highest uint64
}
type Data struct {
count uint64
mValue map[string]Variables
}
func (v Variables) Add(value Variables) Variables {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
return v
}
func (v *Variables) AddPointer(value Variables) {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
}
func main() {
var instances [2]Variables
instances[0] = Variables{sum: 5, highest: 3}
instances[1] = Variables{sum: 10, highest: 2}
var d Data
d.mValue = make(map[string]Variables)
for i:= 0; i < len(instances); i++ {
d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}
fmt.Println(d.mValue["one"])
fmt.Println(d.mValue["two"])
}
我收到错误
# command-line-arguments
/tmp/sandbox209565070/main.go:42: cannot call pointer method on d.mValue["two"]
/tmp/sandbox209565070/main.go:42: cannot take the address of d.mValue["two"]
(我认为)我理解第二个错误cannot take address
- 因为,它是一个地图,它不能取地址(这是正确的吗?)
第一个错误的原因是否相同(不能调用指针方法)?
有没有办法在地图内的结构上使用指针方法..
答案 0 :(得分:2)
是的,同样的道理。为了使用指针接收器调用方法,您需要首先使用指针,或者需要可寻址的值,Go将自动为您指针。
然后,您可以做的是mValue
map[string]*Variables
而不是map[string]Variables
。然后,您将在地图中存储指向已经分配的,保证可寻址的Variables
的指针,并且您将能够在该指针上调用方法。
答案 1 :(得分:1)
扩展上一个答案...
在实践中,这通常不是问题。如果类型在没有指针的情况下更有意义(例如,值语义更有意义的小结构)那么你就不会有指针接收器而且不会出现问题。
如果指针接收器有意义,那么您应该在大多数地方使用指向该类型的指针,例如在地图中(如hobbs said),并且您不会有使用非指针参数或返回非的方法-pointer值(非指针接收器仍然有意义并且易于使用)。同样,问题不会出现。
在第一种情况下,如果您想使用带有非指针映射条目的指针接收器,您可以使用temporary (addressable) variable并将其重新分配回地图。
x := d.mValue["two"]
x.AddPointer(instances[i])
// AddPointer uses a pointer receiver; `x` needs to be addressable,
// it will contain a copy of the value from the map and that copy may
// be changed by the method so we need to copy the new version back
// into the map.
d.mValue["two"] = x
在第二种情况下,出现了一些问题。首先,要避免nil
指针,您需要初始化映射条目或检查映射读取上的nil
/存在(或使指针接收器方法处理nil
值接收器,但是但是对于非指针接收器方法没有帮助。其次,如果由于某些愚蠢的原因你有指针但仍然有一个返回非指针的方法,你必须使用不同的语法来分配给地图。
// Initialize some map entries to avoid nil pointers
d.mValue = map[string]*Variables{
"one": &Variables{},
"two": &Variables{},
}
for i := 0; i < len(instances); i++ {
// Just calling the non-pointer reciever is easy/fine:
d.mValue["one"].Add(instances[i])
// But you can't do this:
//d.mValue["one"] = d.mValue["one"].Add(instances[i])
// cannot use d.mValue["one"].Add(instances[i]) (type Variables) as type *Variables in assignment
*d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}