2017-08-24 97 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