I'm trying to understand Go's type conversion rules. Say we have these interfaces:
type woofer interface {
woof()
}
type runner interface {
run()
}
type woofRunner interface {
woofer
runner
}
and to satisfy the interfaces we have a dog
type:
type dog struct{}
func (*dog) run() {}
func (*dog) woof() {}
These two functions are using the interfaces:
func allWoof(ws []woofer) {}
func oneWoof(w woofer) {}
To use these methods I can write the following:
dogs := make([]woofRunner, 10)
oneWoof(dogs[0])
allWoof(dogs)
The first function oneWoof()
works as expected; a *dog
implements all oneWoof
needs, which is a woof
function.
However for the second function allWoof
, Go won't compile the attempted invocation, reporting the following:
cannot use dogs (type []woofRunner) as type []woofer in argument to allWoof
Using a type conversion is also impossible; writing []woofer(dogs)
fails as well:
cannot convert dogs (type []woofRunner) to type []woofer
Every member of []woofRunner
has all the necessary functions to satisfy a []woofer
, so why is this conversion prohibited?
(I'm not sure if this is the same case explained in the Go FAQ and in various questions on Stack Overflow in which people ask about converting type T
to interface{}
. Every pointer in the slice/array is pointing to a type that is directly convertible to another type. Using these pointers should be possible for the same reason that passing dog[0]
to 'oneWoof` is possible.)
Note 1: I know one solution is to loop over and and convert the items one by one. My question here is why that's necessary and whether there is a better solution.
Note 2: Regarding the rules of Assignability:
A value x is assignable to a variable of type T [when] T is an interface type and x implements T.
Can't we say if the type of the slice/array is assignable to another type, then arrays of those types are also assignable?