Go语言 函数的切片/数组中存储了什么?

fnvucqvd  于 2023-08-01  发布在  Go
关注(0)|答案(2)|浏览(89)

我似乎在文档中找不到答案
给出了这样一个切片:

var funcs []func()

字符串
什么是底层支持阵列?
一开始我以为它会是函数指针数组,但后来我发现这是可能的:

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


其中,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


指示根据接收方方法是通过指针还是通过值,在“同一对象”或其副本上调用该函数。

kgsdhlau

kgsdhlau1#

那么[]func()的底层类型是什么呢?
func()
你似乎面临的概念问题是,方法(或多或少)是Go语言中的普通函数,只是有一个额外的接收器,而不是(调用)签名的一部分。有关此方法值的详细信息,请访问https://go.dev/ref/spec#Method_values。

cedebl8k

cedebl8k2#

除了@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()--这正是切片应该保存的类型。闭包语义也解释了为什么值和指针接收器会有这样的行为。

相关问题