Go 在;“一次旅行”;,如何修改接口,使其需要指针上的方法?

Go 在;“一次旅行”;,如何修改接口,使其需要指针上的方法?,go,Go,在中,我们有这个接口: type Abser interface { Abs() float64 } 据解释,该类型顶点不满足上述Abser: type Vertex struct { X, Y float64 } func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } 如何修改Abser接口以使顶点满足它 (在完整示例中,如果它不再满足MyFloat,那也没关系。) 在我发布这个

在中,我们有这个接口:

type Abser interface {
    Abs() float64
}
据解释,该类型顶点不满足上述Abser:

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
如何修改Abser接口以使顶点满足它

(在完整示例中,如果它不再满足MyFloat,那也没关系。)

在我发布这个问题之前,我花了几个小时搜索和挠头,但在发布之后,我发现了另一个SO问题,涵盖了类似的材料,可能对其他新手有所帮助:


您对什么是实现什么有点困惑。在这种情况下,
*Vertex
正在实现
Abser
,而不是
Vertex
,要使其成为
Vertex
也可以,您必须更改
Abs
实现的接收类型,使其不是指针

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
} // Vertex implementing Abser here
所以你的措辞有点误导。接口不需要更改,也不应收到任何更改。仅供参考,您可以让
*Vertex
Vertex
使用我上面介绍的方法以及您已有的方法来实现该接口

这一点在围棋中经常会让人绊倒。当您声明
func(t SomeType)
时,您正在指定接收类型,如果这是一个类似
(t*SomeType)
的指针,那么实现接口的不是
SomeType
,而是
*SomeType
。这与其他语言略有不同,在其他语言中,方法是由类实现的,不管您使用的是引用还是值。在Go中,类不实现方法,您指定“接收类型”-方法可以调用的对象-第一个参数实际上被推送到堆栈上,并与传递到方法中的参数相同,区别仅与编译相关(接口实现实际上是拥有afaik功能的唯一原因)。因此,总结一下,如果您希望
Vertex
实现
Abser
接口,该接口具有单个方法
Abs()float64
,那么您需要将函数定义为
func(v Vertex)Abs()float64{…}


为了使代码清晰易读,我建议不要同时为指针和值定义接口……您可以使用address of或dereference操作符解决这个问题。

您不能,因为
type Vertex
根本没有任何方法(只有
*Vertex
有方法).谢谢你的详细回答,尽管“有点困惑”有点轻描淡写;我现在感觉特别难受。@DavidSmith我怎样才能帮助消除这种混淆呢?这样想,实现类型就是函数名左边括号中的类型。
AnyType
*AnyType
不是同一类型。无论使用哪种类型,都会影响如果你不熟悉这些接口的区别,我建议你读一下关于指针和值vs引用类型的一些东西。大多数概念在许多系统语言中都是相关的(C,C++,C,等等)。.你很有耐心-我知道如何更改Abs以匹配接口,但我想到的问题是,如何做相反的操作;更改接口以使当前顶点满足它。我想我没有任何使用接口的经验,因此从阅读你的答案来看,这可能只是一个胡说八道;你永远不会定义接口需要类型才能具有只作用于指针的函数的接口?@DavidSmith最后一个问题,是的。您所指的是不可能的,也没有多大意义。在Go中,指针的类型与值版本明显不同。如果您想这样做,则实现接口所需的只是一个函数指针,你可能想使用嵌入。如果你想要的话,我可以详细说明。但是为了提供更多的上下文,这基本上就像在C中的结构上有一个函数指针。对于实现接口的类型,它必须匹配函数定义,因为接口不能由函数指针组成。