对 GO 非常陌生,正在尝试了解频道。我正在尝试创建一个主函数,它将在同一函数中将元素插入通道并从通道打印它。 但如果不将插入部分作为一个单独的函数然后作为 go 例程运行,我就无法做到这一点。 但我无法理解为什么相同的代码不能在单个线程的单个主函数中工作。我收到错误“goroutine 1 [chan receive]: main.main() /path exit status 2”。
工作代码:
package main
import (
"fmt"
)
func inserChannel(c chan int) {
for i := 0; i < cap(c); i++ {
c <- i * i
}
defer close(c)
}
func main() {
c := make(chan int, 10)
go inserChannel(c)
for i := range c {
fmt.Println(i)
}
}
我正在尝试:
package main
import (
"fmt"
)
func main() {
c := make(chan int, 10)
for i := 0; i < cap(c); i++ {
c <- i * i
}
defer close(c)
for i := range c {
fmt.Println(i)
}
}
我想了解为什么第一个有效而第二个无效。当我将它作为普通函数运行时,它甚至可以工作,即不是 go 例程,但如果所有代码都在一个主函数中,则不会。
第二个代码:
它不起作用,因为它尝试在同一主函数内的通道上发送和接收,而没有 goroutine。
原因:
for i := 0; i < cap(c); i++
循环开始向通道发送值。当它发送第一个值时,它会阻塞,等待接收者。随后的 for i := range c
循环应该接收这些值,但它永远没有机会启动,因为第一个循环已经被阻塞。这会创建一个循环依赖关系,其中每个操作都会阻塞另一个操作,从而导致死锁和“goroutine 1 [chan receive]: main.main() /path exit status 2”错误。
第一个代码之所以有效,是因为它利用 goroutine 来同时运行发送和接收操作。
go inserChannel(c)
行启动了一个新的goroutine,它独立执行inserChannel函数。这个 goroutine 开始向通道发送值,允许主函数继续到 for i := range c
循环来接收它们。