Golang 闭包

很多编程语言都闭包的概念,最常见闭包使用的应该是 javascript 了。其实闭包不是什么新奇的概念,就是函数与函数特定环境的组合,闭包使用了本函数之外定义的变量。Golang 中也有所谓的闭包,本文对Golang中的闭包的概念中的关键点通过实际示例进行个简单的说明。

示例1

package main

func add(base int) func(int) int {
    return func(i int) int {
        base += i
        return base
    }
}

func main() {
    tmp1 := add(10)
    fmt.Println(tmp(1), tmp(2))
    tmp2 := add(100)
    fmt.Println(tmp2(1), tmp2(2))
}

结果:

11 13
101 103

示例2

下面是个稍微复杂点的例子

func calc(base int) (func(int) int, func(int) int) {

    add := func(i int) int {
        base += i
        return base
    }

    sub := func(i int) int {
        base -= i
        return base
    }

    return add, sub
}

func main() {
    f1, f2 := calc(10)
    fmt.Println(f1(1), f2(2))
    fmt.Println(f1(3), f2(4))
    fmt.Println(f1(5), f2(6))
    fmt.Println(f1(7), f2(8))
}

结果

11 9
12 8
13 7
14 6

示例3

涉及 goroutine 时的情况

package main

import (
    "fmt"
    "time"
)

func main() {
    for i:=0; i<5; i++ {
        go func(){
            fmt.Println(i)
        }()
    }
    time.Sleep(time.Second)
}

结果:

5
5
5
5
5

通过这三个示例的结果,我们可以了解到闭包中绑定的是外层函数中的变量本身,不是变量当时的值。也就是说闭包中绑定变量的值可以不断变化。但是要注意函数的不同执行会产生不同的闭包,这些闭包之间的变量不是共享,因为函数的每次执行都会重新生成新的局部变量,使得闭包每次绑定的变量不同。

闭包引起的问题

最初使用 goroutine 的时候,曾遇到一个程序死锁的问题。思来想去看代码都觉得问题,最后发现是错误使用闭包导致的问题。
具体代码就不贴了,问题原型如下:

package main

import "fmt"

func main() {
    cs := make([](chan int), 10)
    for i := 0; i < len(cs); i++ {
        cs[i] = make(chan int)
    }

    for i := range cs {
        go func() {
            cs[i] <- i
        }()
    }

    for i := 0; i < len(cs); i++ {
        t := <-cs[i]
        fmt.Println(t)
    }
}

出问题的就是这个地方

for i := range cs {
        go func() {
            cs[i] <- i
        }()
}

由于goroutine还没有开始,i的值已经跑到了最大9,使得这几个goroutine都取的i=9这个值,从而都向cs[9]发消息,导致执行t := <-cs[i]时,cs[0]cs[1]cs[2] … 都阻塞起来了,从而导致了死锁。知道原因,改起来就容易了。
如下:

for i := range cs {
        go func(index int) {
            cs[index] <- index
        }(i)
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值