我想要做的事情:
尝试理解/构建一个具有三个阶段的go管道。第一阶段写入通道A, 第二阶段有多个go例程。每个go例程从通道A读取数据,执行某些操作并将结果写入到Bn通道(B1、B2……Bn)。第三阶段创建n(=第二阶段中通道的总数)个go例程,每个go例程从第二阶段的一个通道中读取数据。这是基于https://blog.golang.org/pipelines所描述的有限并行性。
问题: 管道按预期正常工作,操作被分配给多个go例程。但是当我进行逃逸分析时发现,从一个阶段发送到另一个阶段的通道参数被报告为“泄漏的参数”。
代码片段: 为简单起见,我发布了显示第一阶段通道创建和打印从第一阶段通道读取值的第二阶段的代码。
为什么逃逸分析报告泄漏了in和completionFlag标志的参数?
问题: 管道按预期正常工作,操作被分配给多个go例程。但是当我进行逃逸分析时发现,从一个阶段发送到另一个阶段的通道参数被报告为“泄漏的参数”。
代码片段: 为简单起见,我发布了显示第一阶段通道创建和打印从第一阶段通道读取值的第二阶段的代码。
package main
import "fmt"
func createStageOne(numOfJobs int) <-chan int {
stageOneChannel := make(chan int)
go func(nJobs int) {
for i := 0; i < nJobs; i++ {
stageOneChannel <- i
}
close(stageOneChannel)
}(numOfJobs)
return stageOneChannel
} // stageOneChannel closes and go routine exits once nJobs are completed
func createStageTwo(in <-chan int, completionFlag chan struct{}) {
go func() {
for n := range in {
fmt.Println("Received from stage 1 channel ", n)
}
completionFlag <- struct{}{}
}()
}// Comes out of for loop when stage 1 channel closes and go routine also exits
func main() {
numOfJobs := 10
stageOneChannel := createStageOne(numOfJobs)
done := make(chan struct{})
createStageTwo(stageOneChannel, done)
<-done
}
这是逃逸分析的结果
$ go build -gcflags "-m -l"
# concurrentHTTP/stackoverflow
./pipeline.go:7:5: func literal escapes to heap
./pipeline.go:7:5: func literal escapes to heap
./pipeline.go:6:25: make(chan int) escapes to heap
./pipeline.go:17:5: func literal escapes to heap
./pipeline.go:17:5: func literal escapes to heap
./pipeline.go:16:21: leaking param: in
./pipeline.go:16:36: leaking param: completionFlag
./pipeline.go:19:16: "Received from stage 1 channel " escapes to heap
./pipeline.go:19:16: n escapes to heap
./pipeline.go:19:15: createStageTwo.func1 ... argument does not escape
./pipeline.go:29:14: make(chan struct {}) escapes to heap
为什么逃逸分析报告泄漏了in和completionFlag标志的参数?