我只是在乱搞,写了下面的代码,
package main
import (
"fmt"
)
type Person struct {
name string
}
func (p Person) printName() {
fmt.Println(p.name)
}
type Man struct {
name string
f func()
}
func main() {
p := Person{name: "John"}
m := Man{name: "Adam"}
m.f = p.printName
p.printName()
m.f()
}
上面的代码导致以下输出。这也适用于包。
John
John
所以,这是我的问题。
m.f = p.printName
在上面的示例中执行时会发生什么?这个问题主要涉及接收者,可能会扩展到嵌入。从规范的相关部分:
方法是具有接收器的功能。方法声明将标识符,方法名称绑定到方法,并将该方法与接收者的基本类型相关联。
MethodDecl =“ func”接收器MethodName签名[FunctionBody]。
接收器=参数。
接收器是通过方法名称前面的附加参数部分指定的。该参数部分必须声明一个非可变参数,即接收器。其类型必须为T或* T形式(可能使用括号),其中T为类型名称。用T表示的类型称为接收方基本类型;它不能是指针或接口类型,并且必须在与方法相同的程序包中定义。据说该方法绑定到基本类型,并且方法名称仅在类型T或* T的选择器中可见。
方法签名中的非空白接收者标识符必须唯一。如果没有在方法主体内部引用接收方的值,则可以在声明中省略其标识符。通常,这同样适用于功能和方法的参数。
对于基本类型,绑定到它的方法的非空白名称必须是唯一的。如果基本类型是结构类型,则非空白方法和字段名称必须不同。
给定类型Point,声明
func (p *Point) Length() float64 { return math.Sqrt(p.x * p.x + p.y *p.y) } func (p *Point) Scale(factor float64) { p.x *= factor p.y *= factor }
将接收器类型为* Point的方法Length和Scale绑定到基本类型Point。
方法的类型是将接收方作为第一个参数的函数的类型。
例如,方法Scale具有类型
func(p * Point,factor float64)
但是,以这种方式声明的函数不是方法。
人有一个名为f的字段,它是一个不带参数也不返回任何值的函数。正如我们在上面看到的,golang内部对待
func (p Person) printName()
如
func printName(p Person)
并且当它作用于Person结构时,它可以被认为是没有参数的函数(并且之所以如此,是因为p是一个Person而p.printName作用于p)。因此,可以将其分配给Man.f
因此,当您将Man结构上的f字段分配给一个函数时,该函数已经捕获了名称为“ John”的Person实例并从中读取名称,因此,您将获得打印第二个“ John”的效果。Man.name字段从未在该字段上起作用。
我怀疑通过将Person嵌入到Man中可以实现您期望的正常行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句