Golang闭包

1 形式含义数组

    所谓闭包就是一个函数“捕获”了和它在同一做用于的其余常量和变量。闭包

    从形式上看,在Golang中,全部的匿名函数都是闭包。闭包的建立方式和普通函数几乎一致,只有一个关键区别:闭包没有名字。ide

    咱们来看两个例子函数

addPng := func(name string) string { return name + ".png" }
addJpg := func(name string) string { return name + ".jpg" }
filename := "abc"
fmt.Println(addPng(filename), addJpg(filename))

    结果以下spa

wKioL1YfWKXxKfnzAABdlluUiKs571.jpg

// 工厂函数,返回值也是一个函数
funcaddSuffix(suffix string) func(string) string {
    return func(name string) string {
        if !strings.HasSuffix(name, suffix) {
            name = name + suffix
        }
        return name
    }
}
 
…
 
func main() {
      …
    addZip := addSuffix(".zip")
    addTgz := addSuffix(".tar.gz")
    fmt.Println(addZip(filename),addTgz(filename))
}

wKiom1YfWLfSefPmAABr7vP0oT4056.jpg

2 实质含义blog

    仅仅从形式上将闭包简单理解为匿名函数是不够的,还须要理解闭包实质上的含义。ip

    实质上看,闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。闭包在运行时能够有多个实例,不一样的引用环境和相同的函数组合能够产生不一样的实例。由闭包的实质含义,咱们能够推论:闭包获取捕获变量至关于引用传递,而非值传递;对于闭包函数捕获的常量和变量,不管闭包什么时候何处被调用,闭包均可以使用这些常量和变量,而不用关心它们表面上的做用域。作用域

    咱们用一个例子来进行验证。
get

funcaddNumber(x int) func(int) {
    fmt.Printf("x: %d, addr of x:%p\n", x, &x)
    return func(y int) {
        k := x + y
        x = k
        y = k
        fmt.Printf("x: %d, addr of x:%p\n", x, &x)
        fmt.Printf("y: %d, addr of y:%p\n", y, &y)
    }
}
 
func main() {
    addNum := addNumber(5)
    addNum(1)
    addNum(1)
    addNum(1)
 
    fmt.Println("---------------------")
 
    addNum1 := addNumber(5)
    addNum1(1)
    addNum1(1)
    addNum1(1)
}

    运行结果
string

wKioL1YfWpyhwQw6AAGAfOsAGpQ888.jpg

    首先强调一点,x是闭包中被捕获的变量,y只是闭包内部的局部变量,而非被捕获的变量。所以,对于每一次引用,x的地址都是固定的,是同一个引用变量;y的地址则是变化的。另外,闭包被引用了两次,由此产生了两个闭包实例,即addNum := addNumber(5)addNum1 :=addNumber(5)是两个不一样实例,其中引用的两个x变量也来自两个不一样的实例。

相关文章
相关标签/搜索