2017-03-09 5 views
-1

このプログラムでは、スライス内の特定の実装を返す関数への参照を保存しています。funcのスライスへの参照の保存

SpeakAllの中で、私はそれに対応するオブジェクトを取得し、Speakを呼び出して各関数を呼び出しています。

問題:配列を反復処理し、出力

Go Playground

package main 

import "fmt" 

type IAnimal interface { 
    Speak() string 
} 

type Cat struct {} 
func (c Cat) Speak() string { 
    return "meow!" 
} 

type Dog struct {} 
func (d Dog) Speak() string { 
    return "woof!" 
} 

type Zoo struct { 
    Animals []func() IAnimal 
} 

func (zoo Zoo) AddAnimal(animal func() IAnimal) { 
    if zoo.Animals == nil { 
     zoo.Animals = make([]func() IAnimal, 0) 
    } 
    zoo.Animals = append(zoo.Animals, animal) 
} 

func (zoo Zoo) SpeakAll() { 
    for _, animal := range zoo.Animals { 
     fmt.Println(animal().Speak()) 
    } 
} 


func main() { 
    catFunc := func() IAnimal {return Cat{}} 
    dogFunc := func() IAnimal {return Dog{}} 

    z := Zoo{} 

    z.AddAnimal(catFunc) 
    z.AddAnimal(dogFunc) 

    z.SpeakAll() 
} 
+0

あなたは、例えば、ポインタの方法であることがAddAnimalを必要とします'FUNC(動物園動物園*)AddAnimal(動物FUNC()IAnimal){' https://play.golang.org/p/Tlt4zzz4zH一度ゼロindiexから出発して動物園の動物を除去することが可能 – mkopriva

+0

おかげで、スライスが空になるまでSpeakAllメソッド内の 'Array shift'メソッド –

答えて

0

を取得できませんあなたの問題はAddAnimalは、動物園のタイプのメソッドレシーバ、ない*動物園の型として定義されていることです。これは、あなたがz.AddAnimal(catFunc)を呼び出すときに、このオリジナルの動物園のコピーではなく、本来の動物園に機能を追加する方法、に(スライス動物を含む)動物園のコピーを渡すことを意味します。

変更するには、このようなポインタの受信機への方法、それは、元の構造体へのポインタを受け取ります:

func (zoo *Zoo) AddAnimal(animal func() IAnimal) { 

考慮すべきいくつかの追加のもの:

1 - あなたは必要ありません。 - 次のコード、それがnilかどう追記してスライスを作成します。

if zoo.Animals == nil { 
    zoo.Animals = make([]func() IAnimal, 0) 
} 

2 - ゴーでは、一般的にインターフェースのIとの接頭辞の名前はありません。

3 - あなたが本当にそれで単一のスライスで動物園を持っている場合は、あなただけではなく、カスタムのスライスタイプにメソッドを追加することができます。

type Zoo []func() IAnimal 

func (zoo *Zoo) AddAnimal(animal func() IAnimal) { 
    *zoo = append(*zoo, animal) 
} 

func (zoo Zoo) SpeakAll() { 
    for _, animal := range zoo { 
     fmt.Println(animal().Speak()) 
    } 
} 


func main() { 
    catFunc := func() IAnimal {return Cat{}} 
    dogFunc := func() IAnimal {return Dog{}} 

    var z Zoo 

    z.AddAnimal(catFunc) 
    z.AddAnimal(dogFunc) 

    z.SpeakAll() 
} 
+0

こんにちはコリン@mkopriva –

+0

はい、再びSpeakAllメソッドをポインタ受信者にしてから、範囲の反復後にスライスを切り捨てます。 –

関連する問題