Go 如何制作一个接收自定义接口数组的函数
我正在深入研究Go体系结构,我在多态性方面遇到了问题。我简化了这个问题,并为这个例子创建了新的数据,使我的问题更容易理解 我有这样的结构:Go 如何制作一个接收自定义接口数组的函数,go,interface,polymorphism,Go,Interface,Polymorphism,我正在深入研究Go体系结构,我在多态性方面遇到了问题。我简化了这个问题,并为这个例子创建了新的数据,使我的问题更容易理解 我有这样的结构: type Animal interface { speak() string } type Cat struct { Name string } type Dog struct { Race string } 我想让结构实现接口,我这样做: func (c Cat) speak() string { return
type Animal interface {
speak() string
}
type Cat struct {
Name string
}
type Dog struct {
Race string
}
我想让结构实现接口,我这样做:
func (c Cat) speak() string {
return "Miaw!"
}
func (d Dog) speak() string {
return "Guau!"
}
func speak(a Animal) string {
return a.speak()
}
func speaks(a []Animal) string {
str := ""
for i := 0; i < len(a); i++ {
str += a[i].speak()
}
return str
}
我上传了编译器给我的错误:
有人能给我解释一下为什么我可以在只接收一个元素的函数中使用polimorfish,为什么不能在接收该元素片段的函数中使用polimorfish
我真的需要找到这个问题的解决方案,以便在我的应用程序的不同部分实现它,我不知道如何解决这个问题,也不知道如何实现一个实用且可扩展的解决方案(实际应用程序中的切片将包含大量元素)
我发现这些答案对理解我的问题很有用,但我仍然不知道问题是什么或解决方案是什么:
Go无法键入强制转换数组。您需要手动创建目标类型的新数组,然后使用for循环对源数组的每个元素进行类型转换,并将结果放入目标数组 原因:go不会隐藏内存分配,这就是为什么您需要创建新的并手动感受它的原因 固定版本,在 正如其他人提到的,Go中没有自动类型强制。 猫和动物完全不同 您真正需要做的就是创建一个类型片,该类型片将传递给
speaks
方法。因此,改变:
arrayCats := []Cat{cat1, cat2, cat3}
到
而且效果很好
如果您习惯了Java这样的语言,那么它们的处理方式就完全不同了,因为Java将所有事物都视为一个对象
。因此,当他们添加泛型时,这是一个简单的编译时技巧,其中集合实际上只是对象的列表
,编译器在提取点插入强制转换
像int
这样的东西在java中不是对象,这就是为什么不能创建列表
,因为那样的话列表
施法技巧就不起作用了。因为int
不是Object
的子类
在go中,struct之类的东西没有通用的基类型,因此没有真正的方法来实现java的cast技巧
正如其他人所提到的,go管理内存的方式也有一些特定的功能,这使得自动转换等功能无法以通用方式工作(即:int64的片与int32的片是不同的内存占用,因此在没有分配的情况下不可强制转换)
go团队表示,他们正在考虑以某种形式添加泛型,这可能会使类似的东西更容易编写。但这将带来无形的运行时或编译时复杂性(或两者兼而有之)的代价
今天,由于它不是自动的,您必须编写代码来进行转换。
这样做的缺点是编写更多的代码。它的好处是系统中发生的事情显而易见。我担心该解决方案的性能,它必须对阵列中的每个元素进行大量转换。从干净易读的代码的角度来看,我可以使用这个解决方案,但我认为为每个元素(猫数组和狗数组)创建一个特定的方法将更具性能,因为我们不需要对每个元素进行这种转换,但这将是大量的冗余代码,因为我们为不同的类型复制了相同的方法,这就是语言的局限性吗?还是追求可读性,还是追求性能?并没有组合解决方案?是的,这是语言的局限性,但在现实生活中这是一个非常罕见的问题(你们实现了OOP书中的示例,但在现实生活中我看到的这样的代码非常罕见)。与其“担心性能”,不如用-benchmem和-benchcpu标志测量it运行基准测试,您将看到哪些行实际上慢,哪些行快。@kike,“我担心该解决方案的性能”,这正是Go不为您这样做的原因。它不想对程序员隐瞒。必须写循环才能让成本一目了然。不要包括文本的屏幕截图。而是复制并粘贴文本。如果必须包含图像,请直接将其包含,而不是作为链接。您的
讲话
需要[]动物
,但您尝试使用[]猫
来调用它。这是错误的。这就像试图用[]映射[float64]uint16
调用说话。这两种猫和动物没有任何共同之处。Cat实现Animal这一事实对类型[]Cat
和[]Animal
之间的关系没有任何重要性。停止在Go now和forever中尝试基于继承的OOP,除非你想伤害自己:它不起作用。
arrayCats := []Cat{cat1, cat2, cat3}
arrayCats := []Animal{cat1, cat2, cat3}