Reputation: 13908
I'm trying to identify a type that implements an interface using a switch
:
package main
import "fmt"
type Abser interface {
Abs() float64
}
type Vertex struct {
X, Y int
}
func (v *Vertex) Abs() float64 {
return float64(v.X)
}
func do(i interface{}) {
switch v := i.(type) {
case Abser:
fmt.Println("theres an Abser")
case Vertex:
fmt.Println("theres a Vertex")
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func main() {
do(Vertex{1,2})
}
This code outputs the value for Vertex
instead of Abser
. Ideally it should have output theres an Abser
since Vertex implements the Abs()
method. Is it possible to use a switch-case to do this?
Upvotes: 4
Views: 7318
Reputation: 8232
It is not about the switch command, but about pointer receivers.
If you change func (v *Vertex) Abs() float64
to func (v Vertex) Abs() float64
, it will give the output theres an Abser
.
In general code, a type can use its pointer method - you can call Vertex{1,2}.Abs()
, but what happened behind it is that the Go compiler rewrites it as (&Vertex{1,2}).Abs()
for you. So Vertex
does not implement Abser
.
But on the contrary, a pointer type has all the methods its underlying type has. So even if the API is defined as func (v Vertex) Abs() float64
, &Vertex{1,2}
is still an Abser
. See: https://play.golang.org/p/ONnsjApMywO
See Also:
Method set: https://golang.org/ref/spec#Method_sets
Upvotes: 4
Reputation: 19040
The problem is that Vertex isn't an Abser, only *Vertex is, if you change your Abs() impl to
func (v Vertex) Abs() float64 {
return float64(v.X)
}
then Vertex itself is an Abser and your code will print theres an Abser
Upvotes: 1