英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论