什么时候在 Go 中使用函数表达式而不是函数声明?

Yos*_*nar 3 functional-programming function go

什么时候在 Go 中使用 functioneExpression 而不是函数声明?

我搜索了 Function Expression vs Function Declaration(在 JS 中),它是关于提升的。高朗呢?

icz*_*cza 6

每个都有一个独特的属性:

  • 函数声明 结合的标识符,所述功能名称,到功能; 所以函数名将是一个标识符你可以参考

  • 一个功能文字代表一个匿名函数。函数文字是闭包,它们捕获周围的环境:它们可能引用在周围函数中定义的变量。然后这些变量在周围的函数和函数字面量之间共享,只要它们可访问,它们就会存在。

不要被迷惑:从语法上讲,无论何时使用函数文字,也可以使用声明的函数。例如,以下代码是有效且有效的 Go 代码:

func do() {}

func main() {
    go do()
    defer do()
}
Run Code Online (Sandbox Code Playgroud)

何时使用一种而不是另一种的答案取决于上面列出的独特属性。

当你想引用函数时,当你想重用它时,使用函数声明。这也是分离代码的好方法,函数声明必须在文件级别:不能在另一个函数中声明一个函数。有关详细信息,请参阅函数内的 Golang 嵌套类

当您希望函数能够访问其周围的局部变量和其他标识符时,请使用函数文字。因为你不能在另一个函数中声明一个函数,为了捕获局部变量和标识符,这里唯一的选择是函数文字(除非你想把所有东西作为参数传递给一个声明的函数,如果函数会很快变脏需要修改值,在这种情况下,它们需要“转换”为指针,并且需要传递地址)。对于一个有趣的相关问题,请查看在 Go 中的函数内定义递归函数

当函数不需要命名,函数不需要访问局部变量时,可以根据自己的判断、在其他(质量)项目中看到的例子和之前的经验来选择使用哪一个。如果函数体“小”,则使用函数文字更容易/更简单。如果函数体“大”,如果将其声明为单独的函数并为其提供足够的文档,则代码将更易于阅读和理解。

一个有趣/相关的主题是函数类型的变量,您可以使用函数文字或声明的函数对其进行初始化。它的优点是它是一个标识符,因此您可以引用它,并且可以更改其值并可以为其分配新功能。

例如:

func do() { fmt.Println("Doing...") }

var f = do

func main() {
    f()
    f = func() { fmt.Println("Not doing!") }
    f()
}
Run Code Online (Sandbox Code Playgroud)

上面的输出(在Go Playground上试试):

Doing...
Not doing!
Run Code Online (Sandbox Code Playgroud)

对于在测试中模拟函数非常有用。有关示例,请参阅使用覆盖信息 (coveralls.io/Goveralls) 在 Go 中测试 os.Exit 场景


dev*_*max 5

Go 中的匿名函数用于多种情况:

- 启动 goroutine

go func() {
    // body
}()
Run Code Online (Sandbox Code Playgroud)

- 带有延迟声明

defer func() {
    // body
}()
Run Code Online (Sandbox Code Playgroud)

- 作为另一个函数的参数

err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
    // todo
})
Run Code Online (Sandbox Code Playgroud)

- 作为闭包(示例

当您想通过名称引用函数时,可以使用函数声明。也许可以从您自己的代码中的多个位置调用它,或者将其公开给其他包。