【发布时间】:2020-12-24 22:39:53
【问题描述】:
我正在尝试了解渠道的运作方式。我有这个例子:
import (
"fmt"
"runtime"
"time"
)
func greet(c chan string) {
fmt.Println("1: " + <-c)
fmt.Println("2: " + <-c)
}
func main() {
fmt.Println("main() started")
c := make(chan string, 1)
go greet(c)
c <- "John"
c <- "Mike"
c <- "Mary"
fmt.Println("active goroutines", runtime.NumGoroutine())
c <- "Edward"
time.Sleep(time.Second)
fmt.Println("main() stopped")
}
在执行上述代码时,我看到它给出了一个错误“致命错误:所有 goroutines 都处于睡眠状态 - 死锁!”。但据我了解,在“爱德华”被发送到频道后,执行应该会被阻止。
c <- "Edward"
这个程序应该打印出 Mary 和 Edward 的值。我也不会在任何地方关闭这个频道。谁能告诉我为什么,我该如何解决这个问题?
【问题讨论】:
-
在操场上运行这段代码说明你的理解是正确的。 play.golang.org/p/wh2yqht6Snt
-
您的代码只打印 John 和 Mike,因为您的 goroutine 只有两个打印语句,每个语句都有一个通道接收。您为什么希望它打印更多内容?此外,您可以发送 Mary 而不会导致程序崩溃,因为您使用的是大小为 1 的缓冲通道,并且您不能再发送 Edward,因为没有更多代码可以首先接收 Mary,如果您将大小更改为 2,您将无需添加接收也可以发送 Edward,并且您的程序不会崩溃,但是 Mary 和 Edward 仍然不会被打印,因为您还没有编写任何代码来执行此操作。
-
@mkopriva 那么这是否意味着一旦greet()函数中的所有代码都执行完毕,它将停止运行?
-
是的,就像任何其他功能一样。
go关键字并不意味着“无限期地运行这个函数”,如果这就是你的想法的话。