无法将实现Foo接口的结构体的切片传递给期望[]Foo的函数。

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

Can't pass slices of structs implementing the Foo interface to a function that expects []Foo

问题

我正在尝试在Go语言中使用接口,但似乎无法将实现某个接口的结构体切片传递给期望接口切片的函数。对于只接受单个对象的函数,它可以正常工作,但对于期望接口切片的函数则不行。使用下面的代码,我得到以下错误信息:

./main.go:27: cannot use fooBar (type []*FooBar) as type []Foo in argument to FooBarBar

以下是代码:

package main

import "fmt"

type Foo interface {
	Bar() bool
}

type FooBar struct {
	a bool
}

func (f *FooBar) Bar() bool {
	return f.a
}

func FooBarBar(foos []Foo) {
	for _, foo := range foos {
		fmt.Println(foo.Bar())
	}
}

func main() {
	fooBar := make([]*FooBar, 2)
	fooBar[0] = &FooBar{true}
	fooBar[1] = &FooBar{false}
	FooBarBar(fooBar)
}
英文:

I'm trying to work with interfaces in Go but I can't seem to be able to pass a slice of structs implementing a certain interface to a function that expects a slice of the interface. It works with functions that just takes a single object but not with functions expecting slices of the interface. Using the code below I get the following error:

> ./main.go:27: cannot use fooBar (type []*FooBar) as type []Foo in argument to FooBarBar

Here is the code:

package main

import "fmt"

type Foo interface {
	Bar() bool
}

type FooBar struct {
	a bool
}

func (f *FooBar) Bar() bool {
	return f.a
}

func FooBarBar(foos []Foo) {
	for _, foo := range foos {
		fmt.Println(foo.Bar())
	}
}

func main() {
	fooBar := make([]*FooBar, 2)
	fooBar[0] = &FooBar{true}
	fooBar[1] = &FooBar{false}
	FooBarBar(fooBar)
}

答案1

得分: 1

在Go语言中,没有"子类型化"的概念。

[]Foo[]*Foobar是两种不同的类型,所以你只能使用for循环将[]*Foobar转换为[]Foo

foos := []Foo{}

for _, f := range foobar {
    foos = append(foos, f)
}

FooBarBar(foos)

或者你可以直接将*Foobar放入[]Foo切片中:

foos := []Foo{&FooBar{true}, &FooBar{false}}
FooBarBar(foos)

还有一些例外情况,比如命名类型和未命名类型之间的关系:

type FooBar struct{}

type Foobars []*FooBar // Foobars是一个命名类型,[]*FooBar是一个未命名类型

AcceptFoobars := func(f []*FooBar) {} // 也接受Foobars类型

foobars := Foobars{{}, {}, {}}
AcceptFoobars(foobars)

Go语言的类型系统是"扁平的",没有继承或类型转换,只有断言和转换,这是Go语言规范中定义的。

参考链接:https://golang.org/ref/spec#Types

类型确定了特定类型的值和操作集。类型可以是命名的或未命名的。命名类型由(可能是限定的)类型名称指定;未命名类型使用类型字面量指定,它从现有类型组合成一个新类型。

英文:

There is no "sub typing" in Go.

[]Foo and []*Foobar are 2 different types, so all you can do is use a for loop to convert []*Foobar into []Foo

foos := []Foo{}

for _,f:=range foobar {
    foos = append(foos,f)
}

FooBarBar(foos)

Or you can put your *Foobar directly in a slice of Foo :

foos := []Foo{&FooBar{true},&FooBar{false}}
FooBarBar(foos)

There are a few exceptions like the relationship between named types and unnamed types

type FooBar struct{}

type Foobars []*FooBar // Foobars is an named type, []*FooBar is an unnamed type

AcceptFoobars := func(f []*FooBar) {} // Accepts Foobars too

foobars := Foobars{{}, {}, {}}
AcceptFoobars(foobars)

Go type system is "flat", there is no inheritance or casting, only assertions and conversions. as defined by the Go spec.

https://golang.org/ref/spec#Types

> A type determines the set of values and operations specific to values
> of that type. Types may be named or unnamed. Named types are specified
> by a (possibly qualified) type name; unnamed types are specified using
> a type literal, which composes a new type from existing types.

答案2

得分: 0

可以试试这种方式吗:

func main() {
    fooBar := []Foo{&FooBar{true}, &FooBar{false}}
    FooBarBar(fooBar)
}

GoPlayGround:

英文:

Can i try this way:

func main() {
    fooBar := []Foo{&FooBar{true}, &FooBar{false}}
    FooBarBar(fooBar)
}

GoPlayGround:

huangapple
  • 本文由 发表于 2016年12月6日 01:03:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/40979516.html
匿名

发表评论

匿名网友

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

确定