代码之家  ›  专栏  ›  技术社区  ›  dopatraman

接口类型开关箱

go
  •  1
  • dopatraman  · 技术社区  · 7 年前

    我正在尝试标识一种类型,该类型使用 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 回复  |  直到 7 年前
        1
  •  2
  •   leaf bebop    7 年前

    它不是关于switch命令,而是关于指针接收器。

    如果你改变 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顶点)abs()浮点64 , &Vertex{1,2} 仍然是 缓冲器 . 见: https://play.golang.org/p/ONnsjApMywO

    参见:

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

        2
  •  0
  •   superfell    7 年前

    问题是顶点不是一个abess,只有*顶点是,如果你改变了你的()

    func (v Vertex) Abs() float64 {
        return float64(v.X)
    }
    

    那么vertex本身就是一个abser,您的代码将打印 theres an Abser