将对func的引用保存在切片中

In this program I'm saving references to the functions that are returning specific implementations in a slice.

Within SpeakAll I'm calling each function to get it's corresponding object and calling Speak on it.

Issue: Unable to iterate through array and get an output

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()
}

Your problem is that AddAnimal has been defined as a method receiver on the Zoo type, not the *Zoo type. This means that when you call z.AddAnimal(catFunc) you pass a copy of the Zoo (including the slice Animals) to the method, which then appends the function to this copy of the original Zoo, but not the original Zoo.

Change the method to a pointer receiver like this, and it will receive a pointer to the original struct:

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

Some additional things to consider:

1 - You don't need the following code - append will create the slice if it's nil:

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

2 - In Go you generally don't prefix names with I for interface.

3 - If you really have a Zoo with a single slice in it, you could instead just add methods to a custom slice type:

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()
}