Go 闭包变量作用域

2024-01-23

我正在阅读“CreateSpace Go 2012 编程简介”

在第 86 页我发现了这个邪恶的魔法

func makeEvenGenerator() func() uint {
    i := uint(0)

    return func() (ret uint) {
        ret = i
        i += 2
        return
    }
}

// here's how it's called
nextEven := makeEvenGenerator()
fmt.Println(nextEven())
fmt.Println(nextEven())
fmt.Println(nextEven())

1)为什么是i不重置? 2) 是nextEven()返回和uint or is Println如此聪明,它可以与一切配合?


为了清楚起见,我将为这两个函数指定名称:

func makeEvenGenerator() func() uint { // call this "the factory"
    i := uint(0)

    return func() (ret uint) { // call this "the closure"
        ret = i
        i += 2
        return
    }
}

工厂返回闭包——函数是 Go 中的一等公民,即它们可以是右手表达式,例如:

f := func() { fmt.Println("f was called"); }

f() // prints "f was called"

在您的代码中,闭包包装了工厂的上下文,这称为词汇范围。这就是为什么变量i在闭包内可用,不是作为副本,而是作为对i itself.

该闭包使用了一个命名返回值 called ret。这意味着在闭包内你将隐式声明ret并在此时return,无论什么值ret已经会被退回。

这行:

ret = i

将分配当前值i to ret。不会改变i。然而,这一行:

i += 2

将改变的值i下次调用闭包时。


Here http://play.golang.org/p/zo4mhfqHd2你会发现我为你一起写的一个小闭包示例。它不是很有用,但在我看来很好地说明了闭包的范围、目的和用法:

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())
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go 闭包变量作用域 的相关文章

随机推荐