英文:
Interfaces as map keys
问题
在以下代码中:
package main
import (
"fmt"
)
type Object interface {
String() string
}
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("person: %s", p.Name)
}
func main() {
dict := map[Object]int{
&Person{Name: "xyz"}: 4,
&Person{Name: "gle"}: 2,
&Person{Name: "kp3"}: 7,
}
fmt.Println(dict[&Person{Name: "xyz"}])
}
它只打印出 0
,因为 map 的键是接口类型 Object
。我知道为什么会发生这种情况,但是否有任何方法可以解决这个问题?我希望能够拥有一个键为接口类型的 map,但仍然可以访问字段。
到目前为止,我想到的唯一方法是遍历每个键并检查键是否等于我要搜索的内容,但这可能会非常慢。
英文:
In the following code:
package main
import (
"fmt"
)
type Object interface {
String() string
}
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("person: %s", p.Name)
}
func main() {
dict := map[Object]int{
&Person{Name: "xyz"}: 4,
&Person{Name: "gle"}: 2,
&Person{Name: "kp3"}: 7,
}
fmt.Println(dict[&Person{Name: "xyz"}])
}
It just prints 0
, because the map's keys are Objects
, which are interfaces. I know why this happens, but is there any way to get around it? I want to be able to have a map whose keys are interface types, but which I can still access fields of.
The only way I've thought of so far would be to iterate through each key and check if the key is equal to the thing I'm searching for, but it would likely be significantly slower.
答案1
得分: 4
如果您将方法定义在结构体上而不是指针上,它确实可以工作:https://play.golang.org/p/zU4sbFe2RB。
如果您无法在实际代码中这样做,恐怕您无法实现您想要的效果。即使这两个指针指向相似的数据,它们也将是不同的值。
您可以在Object
接口中添加一个Equals(Object) bool
方法,并自己实现一个映射。或者,您可以定义一个Hash() string
方法,并使用map[string]whatever
。
英文:
It does work if you define your method on a struct rather than a pointer: https://play.golang.org/p/zU4sbFe2RB.
If you can't do that in real code, I'm afraid you can't accomplish what you want. These two pointers will be different values, even if they point to similar data.
You can add an Equals(Object) bool
method to the Object
interface and roll out your own implementation of a map. Alternatively, you can define Hash() string
method and use a map[string]whatever
.
答案2
得分: 3
这似乎是对映射的误用;如果你将映射的键设置为对象的String()
值(对象唯一的共同属性),你可以尝试以下代码:
package main
import (
"fmt"
)
type Object interface {
String() string
}
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("person: %s", p.Name)
}
func main() {
xyz := &Person{Name: "xyz"}
gle := &Person{Name: "gle"}
kp3 := &Person{Name: "kp3"}
dict := map[string]int{
xyz.String(): 4,
gle.String(): 2,
kp3.String(): 7,
}
fmt.Println(dict[xyz.String()])
}
英文:
This seems like it may be a misuse of maps; if you're keying the map off of the String()
value of the objects (the only thing the objects have in common), you might try:
package main
import (
"fmt"
)
type Object interface {
String() string
}
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("person: %s", p.Name)
}
func main() {
xyz := &Person{Name: "xyz"}
gle := &Person{Name: "gle"}
kp3 := &Person{Name: "kp3"}
dict := map[string]int{
xyz.String(): 4,
gle.String(): 2,
kp3.String(): 7,
}
fmt.Println(dict[xyz.String()])
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论