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

时间:2017-09-20 13:14:09

标签: function go functional-programming

何时在Go中使用functioneExpression而不是函数声明?

我搜索了函数表达式与函数声明(在JS中),它是关于提升的。 Golang怎么样?

2 个答案:

答案 0 :(得分:3)

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

- 开始goroutine

go func() {
    // body
}()

- 使用延迟声明

defer func() {
    // body
}()

- 作为另一个函数的参数

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

- 作为闭包(examples

当您想要按名称引用函数时,将使用函数声明。也许在你自己的代码中从多个地方调用它,或者将它暴露给其他包。

答案 1 :(得分:2)

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

  • function declaration 函数名称标识符绑定到函数中;因此,函数名称为identifier ,您可以参考

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

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

func do() {}

func main() {
    go do()
    defer do()
}

使用时,的答案在于上面列出的唯一属性。

如果要重复使用函数,请在需要时使用函数声明。这也是分离代码的好方法,函数声明必须在文件级别:你不能在另一个函数中声明一个函数。有关详细信息,请参阅Golang nested class inside function

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

当函数不需要名称,并且函数不需要访问局部变量时,您可以选择使用哪一个,依赖于您的判断,在其他(质量)项目中看到的示例以及之前的经验。如果函数体是"小",则更容易/更简单地使用函数文字。如果函数体是" big",如果您将代码声明为单独的函数并为其提供足够的文档,则代码将更易于阅读和理解。

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

例如:

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

var f = do

func main() {
    f()
    f = func() { fmt.Println("Not doing!") }
    f()
}

上述输出(在Go Playground上尝试):

Doing...
Not doing!

在测试中模拟函数非常有用。有关示例,请参阅Testing os.Exit scenarios in Go with coverage information (coveralls.io/Goveralls)