问题
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:
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.
来源:https://stackoverflow.com/questions/22825873/passing-a-collection-of-interface-types-to-a-function