将一组接口类型传递给函数

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

Passing a collection of interface types to a function

问题

我在使用Go语言中的接口时遇到了一些困惑。我的函数需要接收一个实现了特定方法的项目映射。代码如下:

type foo interface {
    bar() string
}

func doSomething(items map[string]foo) {

}

我试图使用实现了foo接口的类型调用这个函数。

type baz struct { }

func (b baz) bar() string {
    return "hello"
}

items := map[string]baz{"a": baz{}}
doSomething(items)

但是我得到了以下错误:

cannot use items (type map[string]baz) as type map[string]foo in function argument

然而,当我这样做时,它可以正常工作:

items := map[string]foo{"a": baz{}}
doSomething(items)

但是我想要重用同一个映射来满足不同的接口。基本上,我正在对许多对象进行索引,然后将它们传递给需要实现不同接口以计算结果的各种函数。我想要将映射作为foo类型的映射传递给一个函数,作为foobar类型的映射传递给另一个函数。

我尝试了各种类型断言和转换,但似乎没有任何有效的方法,所以我不确定是我使用的语法不正确还是完全错误。

你可以在Go Playground上查看示例代码:http://play.golang.org/p/8mMWCDG7vm。

英文:

I'm having trouble figuring out the correct way to use interfaces in Go. My function needs to take a map of items that implement a certain method. It looks like this:

type foo interface {
    bar() string
}

func doSomething(items map[string]foo) {

}

I'm trying to call this function with a type that implements the foo interface.

type baz struct { }

func (b baz) bar() string {
    return "hello"
}

items := map[string]baz{"a": baz{}}
doSomething(items)

But I get the following error:

cannot use items (type map[string]baz) as type map[string]foo in function argument

However, it works fine when I do this:

items := map[string]foo{"a": baz{}}
doSomething(items)

But I want to reuse this same map against different interfaces. Basically I'm indexing a lot of objects and then passing them to various functions that require different interfaces implemented to compute results. I want to pass the map to one function as a map of foo and another function as a map of foobar.

I've tried various type assertions and conversions but nothing seems to work so I'm not sure if I'm just not using the correct syntax or just doing it completely wrong.

Go Playground at http://play.golang.org/p/8mMWCDG7vm.

答案1

得分: 2

这是一个相当常见的错误。

你混淆了这两种不同的类型:

map[string]foo

map[string]baz

你不能简单地从一个映射类型转换为另一个映射类型。同样的情况也适用于[]T切片转换为[]interface{}切片,或者chan T转换为chan interface{}(相同的问题/答案,但是针对通道)。

map[string]foo表示一个foo接口的映射,而不是所有类型都是map[string]T,其中T实现了foo接口。

你可以通过进行以下更改来解决这个问题:

items := map[string]foo{"a": baz{}}

Playground: http://play.golang.org/p/HxIVGSptwk

编辑:

拥有一个接口的映射允许你将不同的接口值类型转换为其他类型的接口。因此,该映射可以被重复使用。

Playground: http://play.golang.org/p/20YMWmDjYT

但是,你应该拥有一个接口类型的映射,该接口类型是要存储在映射中的各种类型实现的方法的交集。如果没有交集,那么你将不得不使用interface{}来确保任何类型都可以被存储。

英文:

This is a fairly common mistake.

You are mixing these two distinct types:

map[string]foo

map[string]baz

You cannot simply convert from one map type to another. The same goes with converting []T slices to []interface{} slices, or converting chan T to chan interface{} (same question/answer but for channels).

map[string]foo means a map of foo interfaces, not all types map[string]T where T implements the foo interface.

You can solve it by making this change:

items := map[string]foo{"a": baz{}}

Playground: http://play.golang.org/p/HxIVGSptwk

Edit:

Having a map of interfaces allows you to type cast the different interface values to other types of interfaces. So the map can be reused.

Playground: http://play.golang.org/p/20YMWmDjYT

But then you should have a map of an interface type that is the intersection of all the different methods implemented by the types to be stored in the map. If there is no intersection, then you will have to use interface{} to ensure that any type might be stored.

huangapple
  • 本文由 发表于 2014年4月3日 08:56:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/22825873.html
匿名

发表评论

匿名网友

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

确定