围棋之旅:https://tour.golang.org/methods/9
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f // a MyFloat implements Abser
a = &v // a *Vertex implements Abser
// In the following line, v is a Vertex (not *Vertex)
// and does NOT implement Abser.
a = v
fmt.Println(a.Abs())
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
在本练习中,有两种Abs()
方法。但是似乎第24行fmt.Println(a.Abs())
自动应用了具有与变量相同类型的接收器的接收器。
这是接收器的功能吗?
答案 0 :(得分:2)
The Go Programming Language Specification
类型可能具有与之关联的方法集。一个方法集 接口类型是它的接口。任何其他类型T的方法集 包含所有以接收者类型T声明的方法。方法集 指针类型* T的所有方法的集合 用接收者* T或T声明(也就是说,它还包含方法 T集)。进一步的规则适用于包含嵌入式字段的结构, 如结构类型部分所述。任何其他类型都有 空方法集。在方法集中,每个方法必须具有唯一的 非空白的方法名称。
类型的方法集确定该类型的接口 实现以及可以使用该接收器调用的方法 类型。
类型的方法集确定该类型的接口 实现以及可以使用该接收器调用的方法 类型。
例如,简化Go Tour示例,
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
var a Abser
a = &Vertex{3, 4} // a *Vertex implements Abser
fmt.Println(a.Abs())
}
游乐场:https://play.golang.org/p/cf3WMcBI0WJ
输出:
5
类型a
的变量Abser
可以包含设置了Abser
方法的任何变量类型:Abs() float64
。变量a
包含一个*Vertex
,其满足Abser
的方法集func (v *Vertex) Abs() float64
。表达式a.Abs()
对它当前包含的类型Abs()
执行方法*Vertex
。