2013-12-13 19 views
2

有沒有一種方法可以確定具體類型實現從一個 任意接口列表的接口?我知道一個類型開關,但我想知道所有滿意的 接口。哪些接口滿足任意接口列表?

例如,給定:

type Mover interface { Move() } 
type Talker interface { Talk() } 
type Flyer interface { Fly() } 

type Person struct{} 
func (a *Person) Move() {fmt.Println("Moving...") } 
func (a *Person) Talk() {fmt.Println("Talking...") } 

我可以手動測試每個接口如下:

func testInterfaces(entity interface{}) { 

    _, ok := entity.(Mover) 
    if ok { 
     fmt.Println("mover") 
    } 
    _, ok := entity.(Talker) 
    if ok { 
     fmt.Println("talker") 
    } 
    _, ok := entity.(Flyer) 
    if ok { 
     fmt.Println("flyer") 
    } 
} 

一個人值, 「動子」 和 「講話者」 將打印。但是,我寧願有這樣的(非工作)的功能之一:

func testInterfaces2(entity interface{}, interfaceList type??) { 
    for _, inter := range interfaceList { 
     val, ok := entity.(inter) 
     if ok { 
      // do something with val 
     } 
    } 
} 

有沒有一種方法,我可以實現這樣的僞功能,也許通過反映包或其他方式?

+0

我m不確定,所以我不會發表答案,但我認爲在運行時通過比較檢查接口,沒有滿意接口的主列表。沒有這種事情的一個潛在原因可能允許編譯器優化未使用的接口數據。我懷疑你所要求的不存在,並且不太可能被添加。 – LinearZoetrope

回答

3

你可以使用this獲得的接口類型片。

然後,你可以檢查你的價值Type是否實現了該接口爲here

interfaces := []reflect.Type{reflect.TypeOf((*Mover)(nil)).Elem(), 
    reflect.TypeOf((*Talker)(nil)).Elem(), 
    reflect.TypeOf((*Flyer)(nil)).Elem()} 
p := &Person{} 
t := reflect.TypeOf(p) 
name := t.Elem().Name() 
for _, interf := range interfaces { 
    if t.Implements(interf) { 
     fmt.Printf("%s is a %s\n", name, interf.Name()) 
    } else { 
     fmt.Printf("%s is NOT a %s\n", name, interf.Name()) 
    } 
} 

但我覺得用一個類型的開關是優選的,如果在所有可能的

+0

是的,搜索後,我想出了這個技巧來獲得接口類型。我也建議只有在絕對必要時才使用它。 – LinearZoetrope

2

有一件事情不能很好地處理是泛型。的首選方式做,這是一種開關:

func testInterfaces2(entity interface{}) { 
    switch entity.(type) { 
    case Mover: 
     fmt.Println("mover") 
    case Talker: 
     fmt.Println("talker") 
    case Flyer: 
     fmt.Println("flyer") 
    default: 
     fmt.Println("something else") 
    } 
} 

但像VAL說,讓所有由一個類型實現接口的方式(一個清理的VAL的代碼版本):

package main 

import "fmt" 
import "reflect" 

type Mover interface { Move() } 
type Talker interface { Talk() } 
type Flyer interface { Fly() } 

type Person struct{} 
func (a *Person) Move() {fmt.Println("Moving...") } 
func (a *Person) Talk() {fmt.Println("Talking...") } 

func testInterfaces(entity interface{}, interfaces []reflect.Type) { 
    t := reflect.TypeOf(entity) 
    name := t.Elem().Name() 
    for _, interf := range interfaces { 
      if t.Implements(interf) { 
       fmt.Printf("%s is a %s\n", name, interf.Name()) 
      } else { 
       fmt.Printf("%s is NOT a %s\n", name, interf.Name()) 
      } 
    } 
} 

func main() { 
    interfaces := []reflect.Type{ 
     reflect.TypeOf((*Mover)(nil)).Elem(), 
     reflect.TypeOf((*Talker)(nil)).Elem(), 
     reflect.TypeOf((*Flyer)(nil)).Elem(), 
    } 
    p := &Person{} 
    testInterfaces(p, interfaces) 
} 

這是在去發揮:http://play.golang.org/p/6aqMx5CQvY

+0

類型開關不起作用,因爲交換機在執行Mover情況後退出。儘管Talker接口正常,但「打印機」仍不會被打印出來。我想知道所有滿意的界面。 – Kim