为了更清晰明了,我将为这两个函数分别指定名称:
func makeEvenGenerator() func() uint {
i := uint(0)
return func() (ret uint) {
ret = i
i += 2
return
}
}
工厂函数返回闭包——在Go语言中,函数是一等公民,也就是说它们可以作为右值表达式使用,例如:
f := func() { fmt.Println("f was called"); }
f() // prints "f was called"
在你的代码中,闭包包含了工厂函数的上下文环境,这被称为“词法作用域”。这就是为什么变量i在闭包内部可用,而不是作为副本,而是作为对i本身的引用。
闭包使用了一个名为“ret”的命名返回值。这意味着,在闭包内部你将隐式地声明ret,在return点时,无论ret有什么值,都会被返回。
以下是一行代码:
ret = i
将当前的i
值赋值给ret
。它不会改变i
的值。但是,这行代码:
will assign the current value of i
to ret
. It will not change i
. However, this line:
i += 2
将会改变闭包下一次被调用时i
的值。
这里有一个我写的小闭包示例,虽然不是非常有用,但在我看来很好地说明了闭包的作用域、目的和使用方法:
package main
import "fmt"
func makeIterator(s []string) func() func() string {
i := 0
return func() func() string {
if i == len(s) {
return nil
}
j := i
i++
return func() string {
return s[j]
}
}
}
func main() {
i := makeIterator([]string{"hello", "world", "this", "is", "dog"})
for c := i(); c != nil; c = i() {
fmt.Println(c())
}
}
uint
。请参阅命名结果参数的文档。makeEvenGenerator()
返回一个函数指针(如果可以这样称呼的话)。 - waaadimmakeEvenGenerator
返回一个函数值,而不是指针。因此正确的术语应该是“函数”或“函数值”,但绝对不是函数指针。 - nemo