在接口类型上切换外壳

时间:2018-06-20 04:42:58

标签: go

我正在尝试使用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})
}

此代码输出Vertex而不是Abser的值。理想情况下,它应该具有输出theres an Abser,因为Vertex实现了Abs()方法。是否可以使用开关盒来做到这一点?

2 个答案:

答案 0 :(得分:2)

这与切换命令无关,而与指针接收器有关。

如果将func (v *Vertex) Abs() float64更改为func (v Vertex) Abs() float64,它将得到输出theres an Abser

在一般代码中,类型可以使用其指针方法-您可以调用Vertex{1,2}.Abs(),但其背后发生的是Go编译器为您将其重写为(&Vertex{1,2}).Abs()。因此,Vertex无法实现Abser

但是相反,指针类型具有其基础类型具有的所有方法。因此,即使API被定义为func (v Vertex) Abs() float64&Vertex{1,2}仍然是Abser。参见:https://play.golang.org/p/ONnsjApMywO

另请参见:

方法集:https://golang.org/ref/spec#Method_sets

答案 1 :(得分:0)

问题在于,如果您将Abs()的impl更改为

,则Vertex不是Abser,只有* Vertex是。
func (v Vertex) Abs() float64 {
    return float64(v.X)
}

然后,顶点本身就是Abser,您的代码将显示theres an Abser