2017-08-24 85 views
1

在下面的代码:接口,映射键

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,因为地图的键是Objects,这是接口。我知道为什么会发生这种情况,但有什么办法可以解决它吗?我想能够有一个映射,其键是接口类型,但我仍然可以访问字段。

我想到目前为止唯一的方法是遍历每个键,并检查键是否等于我正在搜索的东西,但它可能会显着减慢

+1

这看起来像一个可能的[XY问题](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) - 你究竟想要完成什么? Map键通常应该只是键,如果你需要从它们到你想要的接口类型的行为,你可能需要考虑一种不同的方法。 – Adrian

+0

我的键是接口类型的原因是因为我正在制作一种程序可以制作地图的语言,其中键_and_值都是相同的类型:一个对象。 – Zac

+0

这并不意味着解释器应该使用Go'map'来实现该语言的地图。 – Adrian

回答

4

它不工作,如果你在一个结构定义你的方法,而不是一个指针:https://play.golang.org/p/zU4sbFe2RB

如果你不能在真正的代码中做到这一点,恐怕你不能完成你想要的。这两个指针将是不同的值,即使它们指向相似的数据。

您可以将Equals(Object) bool方法添加到Object界面并推出您自己的地图实现。或者,您可以定义Hash() string方法并使用map[string]whatever

+1

我可能会实现我自己的地图。 – Zac

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()]) 
} 
+0

好主意,但我不得不改变很多我的代码才能正常工作。 – Zac