如何遍历接口切片?

huangapple go评论83阅读模式
英文:

How do I iterate through a slice of interfaces?

问题

还是对Go语言比较新手。我正在尝试实现这里对我之前问题的建议中提到的答案。在这种情况下,我有一个动物接口和一堆动物结构体。我想能够迭代每个动物并获取它的语言。我尝试了一个指针列表,但是我一直得到一个错误:"y.language未定义(类型animal没有字段或方法language)":

我的代码示例

package main

import "fmt"

type animal interface {
    speak()
}

type dog struct{
    language string
}

func (d *dog) speak() {
    d.language = "woof"
}

var n = []animal{
    &dog{},
}


func main() {
    for _, w := range n{
        x := &dog{}
        fmt.Println(x)
        x.speak()
        fmt.Println(x.language)  // 这个可以工作
        
        fmt.Println(w)
        y := w
        y.speak()
        fmt.Println(y.language)  // 但这个不行...为什么??
    }
}

编辑 #1:为了让我的问题更清楚:为什么 x := &dog{} 能工作,但 y := w 不行?
编辑 #2:对新手没有爱心;(

英文:

Still new to Go. I'm trying to implement the answer as suggested here to my previous question. In this case I have an animal interface and a bunch of animal structs. I want to be able to iterate over each animal & get it's language. I've tried a list of pointers but I keep getting an error "y.language undefined (type animal has no field or method language)":

My playground code

package main

import "fmt"

type animal interface {
    speak()
}

type dog struct{
    language string
}

func (d *dog) speak() {
    d.language = "woof"
}

var n = []animal{
    &dog{},
}


func main() {
    for _, w := range n{
        x := &dog{}
        fmt.Println(x)
        x.speak()
        fmt.Println(x.language)  // this works
        
        fmt.Println(w)
        y := w
        y.speak()
        fmt.Println(y.language)  // but this doesn't...why??
    }
}

EDIT #1: To make my question clearer: Why does x := &dog{} work but y := w does not?
EDIT #2: No love for newbs ;(

答案1

得分: 3

错误是正确的。y := w 声明 yanimal 类型(因为你的 n 切片是 animal 类型)。由于你的 animal 接口不包含 language ... 它不知道该怎么做,因此会出现错误。

你可以使用类型断言来断言它实际上是一个 dog 指针:

fmt.Println(y.(*dog).language)

..然而,我不确定你想要实现什么。

当你引入一个没有 language 属性的 cat 时,你的结构就会出问题。因此,这也会有类似的问题(希望能够展示出你的问题所在):

type cat struct{
}

func (c *cat) speak() {
    // 什么都不做
}

回答你的问题“如何实现一个接口切片?” - 你需要在接口中添加你需要的任何内容,以便以“通用”的方式处理这些项。这意味着将 language 属性转换为 Language() 方法,并通过每个实现 animal 接口的对象返回它。

英文:

The error is correct. y := w is declaring y to be of type animal (as your n slice is of type animal). As your animal interface does not contain language ... it doesn't know what to do and as such it is an error.

You can assert that it is actually a dog pointer by using a type assertion:

fmt.Println(y.(*dog).language)

..however, I am not sure what you're trying to achieve.

Your structure breaks when you introduce a cat that doesn't have a language property too. As such, this will also have similar problems (and hopefully demonstrate where your issue lies):

type cat struct{
}

func (c *cat) speak() {
    // do nothing
}

The answer to your question of "How do I implement a slice of interfaces?" - you need to add whatever you require to the interface in order to process the items "generically". This means turning the language property into a Language() method and returning it via each individual object that implements the animal interface.

huangapple
  • 本文由 发表于 2014年10月20日 08:01:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/26456772.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定