这是一个关于无缓冲通道的简单示例代码:
ch01:= make(chan字符串)
走 </跨度> func(){ fmt.Println(“我们在sub goroutine”) fmt.Println(小于-ch01)}()
fmt.Println(“我们在 主要的goroutine”)ch01&lt; - “你好”
结果我得到了:
我们是主要的goroutine我们在sub goroutine你好
走 </跨度> 操场:https://play.golang.org/p/rFWQbwXRzGw
从我的理解
无缓冲通道阻塞发送,直到接收器准备好读取。在您的第一个示例中,首先设置一个阅读器,因此当发送时,它可以立即发送。
在第二个示例中,发送在接收器准备好之前发生,因此发送块和程序死锁。
您可以通过创建缓冲通道来修复第二个示例,但是有可能您不会看到goroutine的输出,因为程序可能会在刷新输出缓冲区之前退出(主goroutine)。在可以安排之前,goroutine甚至可能不会作为主要出口运行。
首先, go-routines 同时运行。在第一个例子中,sub-goroutine已经启动,但是在第二个例子中,当发送操作出现时,go-routine还没有开始。
go-routines
一点一点地思考。
在第一个例子中, sub-goroutine 在主要的例行程序中出现发送操作之前已同时启动。结果,当发送操作发生时,已经有一个接收器( sub-goroutine )存在。
sub-goroutine
如果你调整第一个例子,
package main import ( "fmt" "time" ) func main() { ch01 := make(chan string) go func() { fmt.Println("We are in the sub goroutine") fmt.Println(<-ch01) }() // wait for start of sub-routine time.Sleep(time.Second * 2) fmt.Println("We are in the main goroutine") ch01 <- "Hello" // wait for the routine to receive and print the string time.Sleep(time.Second * 2) }
输出将是
We are in the sub goroutine We are in the main goroutine Hello
所以,你可以看到sub-goroutine已经开始了。它正在等待在频道上接收。当主goroutine在通道中发送字符串时,sub-goroutine恢复并接收信号。
但是在第二个例子中,程序已经停留在主要的例程中 send operation ,sub go例程还没有开始,也不会启动,因为程序尚未获得该行。所以没有其他接收器接收信号。所以程序陷入僵局。
send operation
对于无缓冲的通道,go例程被阻塞,直到没有人接收它为止。首先应该有一个go例程来从通道接收值,然后发送一个通道值。举例来说,当我们向通道发送一个值时,需要创建一个缓冲通道,以便将值保存到缓冲中,直到没有人接收它为止这样就可以了。
package main import ( "fmt" "time" ) func main() { ch01 := make(chan string, 10) ch01 <- "Hello" go func() { fmt.Println("We are in the sub goroutine") fmt.Println(<-ch01) }() fmt.Println("We are in the main goroutine") time.Sleep(1 * time.Second) }
操场
这是否意味着在ch01&lt; - “Hello”之后主要的goroutine立刻 阻止,以便sub goroutine没有机会跑?如果是真的, 我应该如何理解第一个代码示例的结果?(起初 在主要的goroutine,然后在sub goroutine)。
这是真的。你理解写的东西。未指定产生的goroutine的评估顺序,只能使用同步工具(通道,互斥体)进行控制。第一个示例中的子goroutine也可以在另一个环境中首先打印()。只是 不明 。