goroutine传值和用外部变量有区别吗?

func foo() {
    a : = 'aaaaa'
    b := 'bbbb'
    //一些其他逻辑

    f := 1
    go func(){
        fmt.Println(f)
    }()
}

func foo() {
    a : = 'aaaaa'
    b := 'bbbb'
    //一些其他逻辑

    f := 1
    go func(f int){
        fmt.Println(f)
    }(f)
}

知道第二种传值一般在for循环的时候传递 k 值,比较好奇的是,第一种系统回收 a 和 b 的内存会受影响吗

已邀请:

liunian - root

赞同来自: dncmn keepeye

  • 第一种是指向外部作用域中的 f 变量
  • 第二种是函数自身作用域中的 f 变量

simple - 既要有梦想,又要有实力

赞同来自: keepeye Mrwxj

用这个编译命令试试:go build -gcflags '-m -l' (逃逸分析)

第一种写法(闭包)编译器会将变量f移动heap中,因为会用两个goroutine要访问f;
第二种写法变量f只需要在调用foo函数的goroutine的stack上就可以了。

changjixiong - 时常做白日梦的程序员

赞同来自: keepeye

你需要先分清楚形参、实参 以及变量的作用域

g0194776

赞同来自: keepeye

我的理解是,第一种和第二种不会由于GC的原因导致数据无法访问。

但是这两种方式的差距在哪里呢?我认为在于变量引用的安全性。 相较第一种,第二种方式由于是传递的变量所以在goroutine外侧所使用的变量即便引用被改变,也不会影响到goroutine里面的值。

而如果是第一种方式的话,外面的f一旦改变,则里面的也可能会受到影响。

wangxingge

赞同来自: keepeye

答案大家都说的很清楚了,建议再看一下这个系列的文章,就会更了解原理。 https://www.ardanlabs.com/blog/2017/05/language-mechanics-on-stacks-and-pointers.html

要回复问题请先登录注册