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

我正在深入研究Go体系结构,我在多态性方面遇到了问题。我简化了这个问题,并为这个例子创建了新的数据,使我的问题更容易理解

我有这样的结构:

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}