为什么结构函数与普通函数是相同类型的?

huangapple go评论85阅读模式
英文:

Why are structure functions the same type as ordinary functions

问题

在以下代码中:
struct Struct.Test 的类型是 void func(),这个函数可以获取 Struct t 中的所有参数,为什么 Struct.func()func() 的类型是相同的?

type Struct struct {
	Val string
}

func (t *Struct) Test() {
	println(t.Val)
}

func main() {
	t := Struct{
		Val: "Struct",
	}
	f := t.Test
	f()
	f = func() {
		println("Hello world!")
	}
	f()
}

在这段代码中,Struct.func()func() 的类型是相同的,都是 void func()。这是因为在 Go 语言中,方法和函数的类型是相同的,只是方法需要通过接收者来调用。在这个例子中,Test() 方法是一个带有接收者 t *Struct 的方法,它可以通过 t 来访问结构体 Struct 的成员变量。而 func() 是一个没有接收者的函数,它可以直接调用。尽管它们的调用方式不同,但它们的类型是相同的。

英文:

In following codes:
type of struct Struct.Test is void func(), the function can get all parameters in Struct t, why the types of Struct.func() and func() are the same

type Struct struct {
	Val string
}

func (t *Struct) Test() {
	println(t.Val)
}

func main() {
	t := Struct{
		Val: "Struct",
	}
	f := t.Test
	f()
	f = func() {
		println("Hello world!")
	}
	f()
}

答案1

得分: 1

t.Test 是一个方法值

> 如果表达式 x 的静态类型是 T,并且 M 是类型 T 的方法集中的方法,那么 x.M 被称为 方法值方法值 x.M 是一个函数值,可以使用与调用 x.M 方法相同的参数进行调用。 表达式 x 在方法值的评估过程中被计算和保存;保存的副本随后在任何调用中作为接收器使用,这些调用可能在以后执行。

x.Test() 方法没有参数,所以 x.Test 是一个没有参数的函数。接收器 x 在内部被保存并在以后调用 x.Test 函数值时使用。它的类型将是 func(),所以 f 的类型也是 func(),你可以将任何类型为 func() 的值分配给它。

不要将方法值与方法表达式混淆:

> 如果 M 在类型 T 的方法集中,那么 T.M 是一个函数,可以像常规函数一样调用,参数与 M 的参数相同,只是在前面多了一个参数,该参数是方法的接收器。

方法表达式是应用在_类型_上的,而方法值是应用在_值_上的。方法表达式的结果是一个包含接收器类型的函数值(作为第一个参数),而方法值则不包含(接收器在内部保存)。

所以在你的情况下,方法表达式将是 (*Struct).Test(注意指针:Test() 有指针接收器),它是一个类型为 func(Struct) 的函数。可以像这样使用/调用它:

f2 := (*Struct).Test
f2(&t)

再次输出 Struct,在Go Playground上试一试。

英文:

t.Test is a method value:

> If the expression x has static type T and M is in the method set of type T, x.M is called a method value. The method value x.M is a function value that is callable with the same arguments as a method call of x.M. The expression x is evaluated and saved during the evaluation of the method value; the saved copy is then used as the receiver in any calls, which may be executed later.

The x.Test() method has no parameters, so x.Test is a function without parameters. The receiver x is saved internally and used when you call the x.Test function value later. Its type will be func(), so type of f is also func(), to which you can assign any value that also has a type of func().

Don't confuse method values with method expressions:

> If M is in the method set of type T, T.M is a function that is callable as a regular function with the same arguments as M prefixed by an additional argument that is the receiver of the method.

The method expression is "applied" on a type, while a method value is "applied" on a value. Method expression results in a function value that includes the receiver type (as the first parameter), method value does not (the receiver is saved internally).

So in your case the method expression would be (*Struct).Test (note the pointer: Test() has pointer receiver), and it's a function with type func(Struct). It may be used / called like this:

f2 := (*Struct).Test
f2(&t)

Which again outputs Struct, try it on the Go Playground.

huangapple
  • 本文由 发表于 2022年9月21日 16:20:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/73797504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定