How to write a function which accepts a slice of interfaces and returns a slice of concrete structs?

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

How to write a function which accepts a slice of interfaces and returns a slice of concrete structs?

问题

我目前正在尝试创建一个包,其中包含接受接口(Flyer)并返回具体模型(Bird)的函数。

我有一个描述可以飞行的鸟的接口:

type Flyer interface {
	Fly() string
}

我有一个名为Duck的具体类型,它实现了Fly()方法(满足Flyer接口)。

type Duck struct{}

func (d *Duck) Fly() string {
	return "Duck starts flying"
}

我想编写一个函数,它接受实现Flyer接口的任何结构体的切片,并返回Bird结构体的具体实例。

func NewFlock(f []Flyer) []*Bird {
	result := []*Bird{}
	for _, v := range f {
		isFlying := v.Fly() != ""
		result = append(result, &Bird{
			IsFlying: isFlying,
		})
	}

	return result
}

然而,这导致了以下错误:

./prog.go:38:23: cannot use ducks (variable of type []*Duck) as type []Flyer in argument to NewFlock

根据我的理解,Duck实现了所有方法以满足Flyer接口,那么为什么会导致编译错误呢?

如果这不可能,那么在处理结构体切片时,我该如何遵守以下建议:

接受接口,返回具体实例

完整代码:https://go.dev/play/p/ThsHX7loGlu

英文:

I am currently trying to create a package which comprises of functions which accept interfaces (Flyer) and return concrete models (Bird).

I have an interface, which describes a bird which can fly:

type Flyer interface {
	Fly() string
}

I have a concrete type called Duck, which implements the method Fly() (satisfying the Flyer interface).

type Duck struct{}

func (d *Duck) Fly() string {
	return "Duck starts flying"
}

I want to write a function which accepts a slice of any struct which implements the Flyer interface and return a concretion of the Bird struct.

func NewFlock(f []Flyer) []*Bird {
	result := []*Bird{}
	for _, v := range f {
		isFlying := v.Fly() != ""
		result = append(result, &Bird{
			IsFlying: isFlying,
		})
	}

	return result
}

However, this results in:

./prog.go:38:23: cannot use ducks (variable of type []*Duck) as type []Flyer in argument to NewFlock

Now from my understanding, Duck implements all the methods in order to satisfy the Flyer interface, so why does this result in a compile error?

If this is not possible, how can I abide by the advice:

> accept interfaces, return concretions

when it comes to slices of structs?

Full code: https://go.dev/play/p/ThsHX7loGlu

答案1

得分: 3

为什么这会导致编译错误?

[]Flyer 不是一个接口类型,它是一个具体类型。要能够将值分配给具体类型,被分配的值必须具有相同的类型,或者两个类型必须具有相同的基础类型,并且其中一个必须是无名类型。还有其他规则,请参见:https://go.dev/ref/spec#Assignability

如果你想让代码编译通过,请使用泛型:https://go.dev/play/p/Ygu7dlvgYVf

英文:

> so why does this result in a compile error?

[]Flyer is not an interface type, it is a concrete type, to be able to assign to a concrete type the value being assigned must either have an identical type or the two types need to have identical underlying type and one of them must be unnamed, and there are other rules as well, see: https://go.dev/ref/spec#Assignability

Use generics if you want the code to compile: https://go.dev/play/p/Ygu7dlvgYVf

huangapple
  • 本文由 发表于 2023年1月11日 22:08:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75084353.html
匿名

发表评论

匿名网友

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

确定