1. 首页
  2. 主题
  3. Go语言

关于go的闭包与shadow

zackzhangkai · · 1437 次点击
比如要实现从0到9的打印,需求很简单 原则1: 协程是共享函数的变量的,换句话说:在一个函数中,如果有一个协程,这个协程是可以使用这个函数的变量的。 如下这个执行有问题 ```go func shadow() { for i := 0; i < 10; i++ { go func() { fmt.Println(i) //Question1: 为什么i取不到上面i的值?不是说好协程共享函数的变量的吗,现在怎么背叛我了? }() } time.Sleep(time.Second) } ``` 需要改成如下才行: ```go func shadow() { for i := 0; i < 10; i++ { go func(i int) { fmt.Println(i) }(i) //Question2: 问题跟上面类型,背叛了原则1。因它取不到 i的值。 } time.Sleep(time.Second) } ``` 或是,如下也是可以的 ```go func scope() { for i := 0; i < 10; i++ { i := i //需要加上这个语句,才会从0打印到9;否则打印的不是预期 go func() { fmt.Println(i) }() } time.Sleep(time.Second) } ``` 下面这个示例是对*原则1*的证明,协程确实是共享函数的变量的。 ```go c := make(chan int) go func() { time.Sleep(time.Second * 1) c <- 10 //Question3: 像这里的c它其实是go func外部的变量。但是协程里面,为什么这里又不是个func{}这个函数中的局部变量?为什么这里不需要通过传参的形式来实现? close(c) }() for { select { default: fmt.Printf("%v No Output, now is default\n", time.Now().Format(fmat)) case x, ok := <-c: fmt.Printf("%v, Now step into chan, x:%v, ok:%v\n", time.Now().Format(fmat), x, ok) time.Sleep(time.Second * 5) } } ``` 但是为什么在for range中协程取不到函数的变量呢?
https://www.jianshu.com/p/aceb90f4e571
#1
更多评论
这里关键点在于for k,v range{ go func(){ k }()} ,这个循环内部是局部变量,需要在循环体内定义一个局部变量接收k,v的值,然后go func这个闭包引用外部变量的时候就可以使用这个局部变量,不然每次用的变量都是外部的变量。 总而言之:for range是有内部作用域的。
#2

用户登录

没有账号?注册

今日阅读排行

    加载中

一周阅读排行

    加载中