为什么从 nil 通道读取会增加 Goroutines 的数量?
Why does reading from a nil channel increase the number of Goroutines?
我正在阅读此博客,https://medium.com/golangspec/goroutine-leak-400063aef468,并改编了以下示例,说明了由于从 nil 通道接收而导致的 goroutine 泄漏:
package main
import (
"flag"
"fmt"
"runtime"
"time"
)
var initChannel bool
func main() {
flag.Parse()
var ch chan int
if initChannel {
ch = make(chan int, 1)
ch <- 1
}
go func(ch chan int) {
<-ch
}(ch)
c := time.Tick(1 * time.Second)
for range c {
fmt.Printf("#goroutines: %d\n", runtime.NumGoroutine())
}
}
func init() {
flag.BoolVar(&initChannel, "init", false, "initialize channel")
}
我注意到,如果我 运行 它与 initChannel
false
,goroutines 的数量是 2:
> go run main.go
#goroutines: 2
#goroutines: 2
而如果我 运行 它与 true
,则数字是 1:
> go run main.go --init
#goroutines: 1
#goroutines: 1
不过,我不太明白为什么会这样。我只看到一个 go
语句,所以我希望在任何一种情况下都只有一个 goroutine。为什么从 nil 通道读取时有两个 goroutines?
当您的应用程序启动时,已经有一个 goroutine 运行 main()
函数。
如果您不初始化 ch
通道,它将保持其 zero value which is nil
for channels. Spec: Receive operator:
Receiving from a nil
channel blocks forever.
详情见
所以如果通道是nil
,启动的goroutine将永远不会结束。因此,您将有 2 个 goroutine:main
goroutine 和您启动的那个。
如果您使用 1 个缓冲区初始化通道并在其上发送一个值,那么对于一个 "short period of time",您还将有 2 个 goroutines,但是启动的 goroutine 可以从中接收一个值,然后立即结束。所以将剩下一个 goroutine,main
goroutine。
我正在阅读此博客,https://medium.com/golangspec/goroutine-leak-400063aef468,并改编了以下示例,说明了由于从 nil 通道接收而导致的 goroutine 泄漏:
package main
import (
"flag"
"fmt"
"runtime"
"time"
)
var initChannel bool
func main() {
flag.Parse()
var ch chan int
if initChannel {
ch = make(chan int, 1)
ch <- 1
}
go func(ch chan int) {
<-ch
}(ch)
c := time.Tick(1 * time.Second)
for range c {
fmt.Printf("#goroutines: %d\n", runtime.NumGoroutine())
}
}
func init() {
flag.BoolVar(&initChannel, "init", false, "initialize channel")
}
我注意到,如果我 运行 它与 initChannel
false
,goroutines 的数量是 2:
> go run main.go
#goroutines: 2
#goroutines: 2
而如果我 运行 它与 true
,则数字是 1:
> go run main.go --init
#goroutines: 1
#goroutines: 1
不过,我不太明白为什么会这样。我只看到一个 go
语句,所以我希望在任何一种情况下都只有一个 goroutine。为什么从 nil 通道读取时有两个 goroutines?
当您的应用程序启动时,已经有一个 goroutine 运行 main()
函数。
如果您不初始化 ch
通道,它将保持其 zero value which is nil
for channels. Spec: Receive operator:
Receiving from a
nil
channel blocks forever.
详情见
所以如果通道是nil
,启动的goroutine将永远不会结束。因此,您将有 2 个 goroutine:main
goroutine 和您启动的那个。
如果您使用 1 个缓冲区初始化通道并在其上发送一个值,那么对于一个 "short period of time",您还将有 2 个 goroutines,但是启动的 goroutine 可以从中接收一个值,然后立即结束。所以将剩下一个 goroutine,main
goroutine。