英文:
Generic function using embeddable structs
问题
我正在尝试编写一个函数,该函数将处理某种类型的对象,并调用作为参数之一传递的特定方法。由于Go语言中没有继承或泛型,我正在使用嵌入(embedding)。(我不能使用接口,因为接口只能定义方法,而我还需要结构体字段。)
我对Go语言还不熟悉,所以肯定做错了一些事情。以下是我代码的简化版本:
package main
import "fmt"
import "reflect"
type Animal struct {
Type string
}
type Dog struct {
Animal
}
type Cat struct {
Animal
}
func (d *Dog) SayWoof() {
fmt.Println("WOOF")
}
func (c *Cat) SayMeouw() {
fmt.Println("MEOUW")
}
func CallMethod(animal interface{}, baseAnimal *Animal, methodName string) {
fmt.Println("Animal type: ", baseAnimal.Type)
method := reflect.ValueOf(animal).MethodByName(methodName)
if !method.IsValid() {
return
}
method.Call([]reflect.Value{})
}
func main() {
dog := &Dog{}
dog.Type = "Dog" // for some reason dog := &Dog{Type: "Dog"} doesn't compile
cat := &Cat{}
cat.Type = "Cat"
CallMethod(dog, &dog.Animal, "SayWoof")
CallMethod(cat, &cat.Animal, "SayMeouw")
}
输出结果:
Animal type: Dog
WOOF
Animal type: Cat
MEOUW
这段代码可以工作,但是我基本上需要两次传递对象:首先是一个接口来动态调用方法,然后是嵌入的("父")对象来访问其字段。
我更希望有这样的函数定义:
func CallMethod(animal Animal, methodName string)
但是,如果将Dog
对象强制转换为Animal
对象,像这样:
CallMethod(dog.Animal, "SayWoof")
显然不起作用,因为Animal
中没有定义"SayWoof"方法。
所以问题是:有没有办法只传递一个子对象给函数,并访问其所有的反射数据?
谢谢!
英文:
I'm trying to write a function that will process a certain type of objects and call a certain method passed as one of the args. Since there's no inheritance or generics, I'm using embedding. (I can't use interfaces as you can only define methods in them, and I need struct fields as well).
I'm new at Go, so I'm definitely doing something wrong. Here's a simplified version of my code:
http://play.golang.org/p/r0mtDXtmWc
package main
import "fmt"
import "reflect"
type Animal struct {
Type string
}
type Dog struct {
Animal
}
type Cat struct {
Animal
}
func (d *Dog) SayWoof() {
fmt.Println("WOOF")
}
func (c *Cat) SayMeouw() {
fmt.Println("MEOUW")
}
func CallMethod(animal interface{}, baseAnimal *Animal, methodName string) {
fmt.Println("Animal type: ", baseAnimal.Type)
method := reflect.ValueOf(animal).MethodByName(methodName)
if !method.IsValid() {
return
}
method.Call([]reflect.Value{})
}
func main() {
dog := &Dog{}
dog.Type = "Dog" // for some reason dog := &Dog{Type: "Dog"} doesn't compile
cat := &Cat{}
cat.Type = "Cat"
CallMethod(dog, &dog.Animal, "SayWoof")
CallMethod(cat, &cat.Animal, "SayMeouw")
}
output:
Animal type: Dog
WOOF
Animal type: Cat
MEOUW
This code works, but I basically need to pass an object twice: first an interface to call a method dynamically and then the embedded ("parent") object to get access to its fields.
I would much rather have something like
func CallMethod(animal Animal, methodName string)
but then if cast a Dog
object to an Animal
like this:
CallMethod(dog.Animal, "SayWoof")
it obviously won't work as there's no "SayWoof" method defined in Animal.
So the question is: is there a way to pass a child object to a function once and have access to all its reflection data?
Thanks
答案1
得分: 1
包 main
import "fmt"
type Animal interface {
Speak()
}
type Dog struct {
}
type Cat struct {
}
func (d *Dog) Speak() {
fmt.Println("Woof")
}
func (c *Cat) Speak() {
fmt.Println("Meow")
}
func Speaketh(a Animal) {
a.Speak()
}
func main() {
dog := Dog{}
cat := Cat{}
Speaketh(&dog)
Speaketh(&cat)
}
你对泛型语言到底有什么期望来解决你的问题呢?这是一个诚实的问题。对于你想要调用"SayMeow"和"SayWoof"这两个不同的函数名,没有任何类型不可知的数据结构能够帮助你神奇地调用正确的函数。
英文:
package main
import "fmt"
type Animal interface {
Speak()
}
type Dog struct {
}
type Cat struct {
}
func (d *Dog) Speak() {
fmt.Println("Woof")
}
func (c *Cat) Speak() {
fmt.Println("Meow")
}
func Speaketh(a Animal) {
a.Speak()
}
func main() {
dog := Dog{}
cat := Cat{}
Speaketh(&dog)
Speaketh(&cat)
}
How exactly would you expect a language with generics to solve your problem anyway? That's an honest question. With different function names you want to call "SayMeow" and "SayWoof", no type agnostic data structure is going to help you magically call the right thing.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论