英文:
Saving references to the func's in a slice
问题
在这个程序中,我将返回特定实现的函数的引用保存在一个切片中。
在SpeakAll函数中,我调用每个函数以获取其对应的对象,并调用其Speak方法。
问题:无法遍历数组并获取输出。
以下是翻译好的代码:
package main
import "fmt"
type IAnimal interface {
Speak() string
}
type Cat struct {}
func (c Cat) Speak() string {
return "喵喵!"
}
type Dog struct {}
func (d Dog) Speak() string {
return "汪汪!"
}
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()
}
你可以在Go Playground上运行这段代码。
英文:
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
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()
}
答案1
得分: 0
你的问题是AddAnimal方法被定义为Zoo类型的方法接收器,而不是*Zoo类型。这意味着当你调用z.AddAnimal(catFunc)时,你将一个Zoo的副本(包括切片Animals)传递给该方法,该方法将函数追加到这个副本的原始Zoo中,而不是原始的Zoo。
将该方法改为指针接收器,像这样,它将接收到原始结构体的指针:
func (zoo *Zoo) AddAnimal(animal func() IAnimal) {
还有一些其他需要考虑的事项:
1 - 你不需要以下代码-如果切片为nil,append函数会创建一个切片:
if zoo.Animals == nil {
zoo.Animals = make([]func() IAnimal, 0)
}
2 - 在Go语言中,通常不会在接口名称前加上I前缀。
3 - 如果你真的有一个只包含一个切片的Zoo,你可以直接为自定义切片类型添加方法:
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()
}
英文:
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论