go - 为什么接口(interface)分配比方法调用更严格?

标签 go interface

我正在经历围棋之旅。我了解到,如果我们有一个接受指针作为接收器的方法,它也会接受一个值类型作为接收器(go 会自动进行转换)。

type Vertex struct { X, Y float64 }

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
那么下面的代码是有效的,无论是通过值还是指针接收Vertex
v := Vertex{1, 2}
fmt.Println(v.Abs())

p := &v
fmt.Println(p.Abs())
但是,假设我们有以下接口(interface):
type Abser interface {
    Abs() float64
}
那么,为什么下面的代码无效呢?
var a Abser
v := Vertex{1, 2}

a = v // invalid
我的理解是这样就可以了。即使 v 是一个值类型,它“实现”了接受指针接收器的 Abs 函数,它也会按值接受它吗?
接口(interface)是否只是为了更严格地定义接口(interface)变量可以在右侧保存的内容而设计?该接口(interface)将 *Vertex 和 Vertex 视为两种不同的类型,但是 Abs() 方法也没有问题处理。

最佳答案

在这两种情况下,Go 都需要一个指针来运行该方法。最大的不同是方法调用会自动取v的地址。 ,但检查某物是否实现了接口(interface)并没有。
方法调用:
在普通类型上调用带有指针接收器的方法时,如果允许,Go 将自动获取地址。来自 spec on method calls (重点是我的):

A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()


在这种情况下,x指您的变量 v并且是 addressable .所以在方法调用时,Go 会自动运行 (&v).Abs() .
任务:
当试图 assign a = v ,必须填写的支票是T is an interface type and x implements T. . v实现 Abser仅当它的 method set匹配界面。该方法集确定如下:

The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).


你会注意到,在计算方法集时,Go 并没有采用 v 的地址。就像在方法调用中所做的那样。 这意味着为 var v Vertex 设置的方法为空,未能实现接口(interface)。
解决方案:
解决这个问题的方法是获取 v 的地址你自己:
var a Abser
v := Vertex{1, 2}

a = &v
通过这样做,您现在正在查看 *Vertex 的方法集其中包括Abs() float64从而实现接口(interface)Abser .

关于go - 为什么接口(interface)分配比方法调用更严格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63498619/

相关文章:

data-binding - 绑定(bind) IList<IMyInterfaceType> 不显示 IMyInterface 继承的接口(interface)的成员

file-io - 如何使用 "compress/gzip"包来 gzip 文件?

http - 对每个请求使用不同的代理

json - 去解析数组的JSON数组

java - 接口(interface) Iterator 已经在 J​​ava 中定义了?

java - "this"关键字在实现接口(interface)(java)的类中意味着什么?怎么会作为接口(interface)发送呢?

Go:嵌入式后端与应用引擎

go - 如何调整用于下载 N 个文件的 goroutine 数量?

c# - 扩展现有接口(interface)

java - 单例标签接口(interface)