切片/数组中存储的是函数。

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

What is stored in a slice/array of funcs?

问题

在文档中似乎找不到答案。

给定一个切片:

var funcs []func()

底层的支持数组是什么?

起初我以为它会是一个函数指针的数组,但后来我发现这是可能的:

funcs = append(funcs, f.SomeFunc)
funcs[0]() // 在f上调用SomeFunc

其中f是任何具有为其定义的方法/接收器函数的类型。

那么底层的实现是什么呢?

示例程序:

package main

import "fmt"

func PrintStandalone() {
    fmt.Println("Standalone")
}

type Point struct {
    x int
    y int
}

func (p *Point) PrintPoint() {
    fmt.Println("X: ", p.x, " Y: ", p.y)
}

type Coordinate struct {
    lat  int
    long int
}

func (c Coordinate) PrintCoordinate() {
    fmt.Println("Lat: ", c.lat, " Long: ", c.long)
}

func main() {

    p := Point{x: 1, y: 2}
    c := Coordinate{lat: 3, long: 4}

    var funcs []func()

    funcs = append(funcs, PrintStandalone)
    funcs = append(funcs, p.PrintPoint)
    funcs = append(funcs, c.PrintCoordinate)

    for _, fn := range funcs {
        fn()
    }

    p = Point{x: 5, y: 6}
    c = Coordinate{lat: 7, long: 8}

    for _, fn := range funcs {
        fn()
    }
}

运行此程序会打印:

Standalone
X:  1  Y:  2
Lat:  3  Long:  4
Standalone
X:  5  Y:  6
Lat:  3  Long:  4

这表明,根据接收器方法是通过指针还是通过值,函数是在“相同对象”上调用还是在其副本上调用。

英文:

I cannot seem to find an answer anywhere in the documentation

Given a slice like:

var funcs []func()

What is the underlying backing array?

At first I thought it would be an array of function pointers, but I have since seen that this is possible:

funcs = append(funcs, f.SomeFunc)
funcs[0]() // calls SomeFunc on the f 

Where f is any type that has a method/receiver function defined for it.

So what is the underlying implementation?

Example program

package main

import "fmt"

func PrintStandalone() {
	fmt.Println("Standalone")
}

type Point struct {
	x int
	y int
}

func (p *Point) PrintPoint() {
	fmt.Println("X: ", p.x, " Y: ", p.y)
}

type Coordinate struct {
	lat  int
	long int
}

func (c Coordinate) PrintCoordinate() {
	fmt.Println("Lat: ", c.lat, " Long: ", c.long)
}

func main() {

	p := Point{x: 1, y: 2}
	c := Coordinate{lat: 3, long: 4}

	var funcs []func()

	funcs = append(funcs, PrintStandalone)
	funcs = append(funcs, p.PrintPoint)
	funcs = append(funcs, c.PrintCoordinate)

	for _, fn := range funcs {
		fn()
	}

	p = Point{x: 5, y: 6}
	c = Coordinate{lat: 7, long: 8}

	for _, fn := range funcs {
		fn()
	}
}

When run, this program prints

Standalone
X:  1  Y:  2
Lat:  3  Long:  4
Standalone
X:  5  Y:  6
Lat:  3  Long:  4

Indicating that, depending on whether the receiver method is by pointer or by value, the function is called on the "same object" or on a copy of it.

答案1

得分: 2

"所以[]func()的底层类型是什么?"

它的底层类型是func()

你似乎面临的概念问题是,在Go语言中,方法(method)实际上就是普通函数,只是多了一个不属于(调用)签名的接收者(receiver)。关于方法值的详细信息可以在这里找到:https://go.dev/ref/spec#Method_values。

英文:

> So what is the underlying type [of []func()]?

It is func().

The conceptual problem you seem to face is that methods are (more or less) plain functions in Go just having an additional receiver that is not part of the (call) signature). Details on this method values can be found here https://go.dev/ref/spec#Method_values.

答案2

得分: 1

除了@Volker的答案之外,想象方法是返回闭包的函数可能也有所帮助。也就是说,

func (p *Point) PrintPoint() {
    fmt.Println("X: ", p.x, " Y: ", p.y)
}

在概念上与

func PrintPoint(p *Point) func() {
    func() {
        fmt.Println("X: ", p.x, " Y: ", p.y)
    }
}

是相同的。现在,p.PrintPoint 只是一个简单的函数调用 PrintPoint(&p),它返回一个 func() 类型,这正是你的切片应该保存的确切类型。闭包的语义也解释了为什么值接收器和指针接收器的行为方式是这样的。

英文:

In addition to @Volker's answer, it might also help to imagine methods as functions that return closures over their receiver. I.e.

func (p *Point) PrintPoint() {
    fmt.Println("X: ", p.x, " Y: ", p.y)
}

is conceptually the same as

func PrintPoint(p *Point) func() {
    func() {
        fmt.Println("X: ", p.x, " Y: ", p.y)
    }
}

Now p.PrintPoint just becomes a simple function invocation PrintPoint(&p) which returns a func() -- the exact type your slice is supposed to hold. The closure semantics also explain why value and pointer receivers behave the way they do.

huangapple
  • 本文由 发表于 2023年6月27日 20:33:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564913.html
匿名

发表评论

匿名网友

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

确定