今天在分析代码时候,突然想到一个事情,在使用channel时候,我看了代码,里面传递的数据时指针类型的。我当时就在考虑,这种做法会不会导致GC压力过大,然后我进行的测试发现的确会比没有指针类型的压力大点(也不是很多)。 后面我考虑想着能不能换成非指针数据,然后我突然考虑到了一个问题,我们一般接收channel数据时候,都是在一个func中处理,比如:
func rcv() {
for {
p := <-pc
p.A = 1
}
}
这种方式。这里的pc传递的是非指针数据。我想了一下,也没有发生逃逸,那么问题来了: 这里的p会分配在栈上,那我的程序一直跑着,不会导致栈空间不足吗?然后还是被分配在堆上? 求解这里问题,有点没搞懂
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)
看到一篇文章:Golang 元素值在经过通道传递时会被复制,这个复制是浅复制
如果通道传递值类型,实际就是完整的复制,发送端和接收端的数据不是同一个,所以不存在逃逸。
如果传递引用类型,由于只是引用被复制,例如指针地址被传过去了,这时候就存在逃逸。
这个我知道,问题是,就我了解的,没有逃逸的数据分配在函数栈上,然后等函数结束时候,就被一起释放。但是我这个函数,是一直运行,一直接收数据,问题就是数据会一直分配在栈上,不会导致栈空间不足吗?还是我对栈这里的理解有问题。。
我运行了如下代码,浏览器打开 http://127.0.0.1:4500/debug/pprof/ ,然后点击
allocs
,一直刷新页面看到Stack =
栈分配没有增加,所以我觉得不会随着程序的运行导致栈空间占满。点击heap
里面的Stack =
也是没有增加的。在for循环里面,变量始终是同一个。
比如
p := <-pc
里面的p
在for循环里面始终是同一个栈空间,如果没有其它变化内存并不会增长。我自己也实践了一下,我跑了十几分钟,使用了指针的channel和非指针的channel,但是看了trace的gc图,感觉差不多。![image.png](https://static.golangjob.cn/220624/a31f64a7da7a094f8bb4a5a8f25dbbb1.png)
上面是参数是指针的
我草了,好像是这样的。类似于
for v:=range channel
一语惊醒梦中人。
我打印了变量地址,貌似每次都是新生成的,不是同一个吧。
p的地址就一个每次循环值不同, 就行for range一样
p 在执行完即释放 不会栈溢出
每个goroutine 都有各自的栈空间。单单一个就更是占不了什么空间。
如果p 过大还是会分在堆上的。
各自的的routine 又是抢占式的。也只能并行cpu 线程数个数来运行。
栈溢出一般至少需要很多M。具体的忘记怎么算来。