问题
I am struggling with Go's Type Assertion mechanism. In the below example the Type Assertion for Qux.(Bar) fails.
Why does a direct implementation of DoBar() at Qux not fullfill the Bar interface?
package main
import (
"fmt"
)
type Nameable interface {
Name() string
}
type Foo interface {
Nameable
DoFoo() string
}
type Bar interface {
Nameable
DoBar() string
}
type bar struct {
name string
}
func (b bar) Name() string {
return b.name
}
// Qux embeds bar and is expected to fullfill Nameable interface
type Qux struct {
bar
}
func (q *Qux) DoBar() string {
return "DoBar"
}
func Check(subject Nameable) {
if N, ok := subject.(Nameable); ok {
fmt.Printf("%s has Nameable\n", N.Name())
}
if F, ok := subject.(Foo); ok {
fmt.Printf("%s has Foo: %s\n", F.Name(), F.DoFoo())
}
if B, ok := subject.(Bar); ok {
fmt.Printf("%s has Bar: %s\n", B.Name(), B.DoBar())
}
}
func main() {
Check(bar{name: "bar"})
Check(Qux{bar: bar{name: "Qux"}})
}
https://play.golang.org/p/PPkUMUu58JW
Output:
bar has Nameable
Qux has Nameable
回答1:
Qux.DoBar() has pointer receiver, so only *Qux implements Bar but not Qux. The type Qux and the pointer type to it *Qux are different types with different method sets.
Using a value of type *Qux does implement Bar:
Check(&Qux{bar: bar{name: "*Qux"}})
This outputs (try it on the Go Playground):
*Qux has Nameable
*Qux has Bar: DoBar
Also if you change the receiver of Qux.DoBar() to be non-pointer:
func (q Qux) DoBar() string {
return "DoBar"
}
Then both Qux and *Qux will implement Bar:
Check(bar{name: "bar"})
Check(Qux{bar: bar{name: "Qux"}})
Check(&Qux{bar: bar{name: "*Qux"}})
Output (try it on the Go Playground):
bar has Nameable
Qux has Nameable
Qux has Bar: DoBar
*Qux has Nameable
*Qux has Bar: DoBar
See related question: X does not implement Y (... method has a pointer receiver)
来源:https://stackoverflow.com/questions/52739991/why-does-this-type-assertion-on-a-direct-implemented-interface-fail