Go channels publish, receive and go routine scheduling
Go channels publish, receive and go routine scheduling
我有以下一段 go 脚本,我对通道读取数据和 go 例程的执行顺序有疑问。
package main
import "fmt"
func squares(c chan int) {
fmt.Println("started squares goroutine...")
for num := range c {
//num := <-c
fmt.Println(num * num)
}
fmt.Println("exiting squares goroutine...")
}
func main() {
fmt.Println("main() started")
c := make(chan int, 3)
go squares(c)
c <- 1
printChannel(c)
c <- 2
printChannel(c)
c <- 3
printChannel(c)
c <- 4
fmt.Println("after publish 4")
printChannel(c)
c <- 5
fmt.Println("after publish 5")
printChannel(c)
c <- 6
printChannel(c)
c <- 7
printChannel(c)
c <- 8
printChannel(c)
fmt.Println("main() stopped")
}
func printChannel(c chan int) {
fmt.Println("length: ",len(c))
fmt.Println("capacity: ",cap(c))
}
输出:
main() started
length: 1
capacity: 3
length: 2
capacity: 3
length: 3
capacity: 3
started squares goroutine...
1
4
9
16
after publish 4
length: 0
capacity: 3
after publish 5
length: 0
capacity: 3
length: 1
capacity: 3
length: 2
capacity: 3
length: 3
capacity: 3
main() stopped
问题:
创建的通道 ch 的容量是 3,但是直到 4 被发布到通道之前,通道不会在 squares go 例程中读取,如果容量是 3,那么 4 存储在频道
从通道中读取完所有数字后,再次将数字5发布到通道中,但通道的长度仍然为0,为什么?
Goplayground link 代码:https://play.golang.org/p/TmCcZt5n58f
无法保证 goroutine 的执行顺序,也无法保证 goroutine 何时中断(I/O,包括打印到 stdout,将是重新安排的最常见原因)。
关于你的第一个问题:你可以看到 16
在 after publish 4
之前被打印出来了。这意味着 squares
goroutine 在主 goroutine 可以开始打印信息之前从通道读取并打印正方形。当主 goroutine 尝试打印通道的长度时,4
已经消失了。
同理,发送5
到channel后,squares
goroutine已经收到了,但是还没有打印出来。它在打印之前被打断了。这意味着频道又是空的,但我们还没有看到25
。
如果您多次 运行 您的示例,您会看到不同的输出。有时 squares
goroutine 会一直运行到 64
,有时则不会。这是完全正常的。在普通代码中,你需要确保在退出之前等待数据被消费,并且你不会依赖于不同goroutines的执行顺序或时间。
我有以下一段 go 脚本,我对通道读取数据和 go 例程的执行顺序有疑问。
package main
import "fmt"
func squares(c chan int) {
fmt.Println("started squares goroutine...")
for num := range c {
//num := <-c
fmt.Println(num * num)
}
fmt.Println("exiting squares goroutine...")
}
func main() {
fmt.Println("main() started")
c := make(chan int, 3)
go squares(c)
c <- 1
printChannel(c)
c <- 2
printChannel(c)
c <- 3
printChannel(c)
c <- 4
fmt.Println("after publish 4")
printChannel(c)
c <- 5
fmt.Println("after publish 5")
printChannel(c)
c <- 6
printChannel(c)
c <- 7
printChannel(c)
c <- 8
printChannel(c)
fmt.Println("main() stopped")
}
func printChannel(c chan int) {
fmt.Println("length: ",len(c))
fmt.Println("capacity: ",cap(c))
}
输出:
main() started
length: 1
capacity: 3
length: 2
capacity: 3
length: 3
capacity: 3
started squares goroutine...
1
4
9
16
after publish 4
length: 0
capacity: 3
after publish 5
length: 0
capacity: 3
length: 1
capacity: 3
length: 2
capacity: 3
length: 3
capacity: 3
main() stopped
问题:
创建的通道 ch 的容量是 3,但是直到 4 被发布到通道之前,通道不会在 squares go 例程中读取,如果容量是 3,那么 4 存储在频道
从通道中读取完所有数字后,再次将数字5发布到通道中,但通道的长度仍然为0,为什么?
Goplayground link 代码:https://play.golang.org/p/TmCcZt5n58f
无法保证 goroutine 的执行顺序,也无法保证 goroutine 何时中断(I/O,包括打印到 stdout,将是重新安排的最常见原因)。
关于你的第一个问题:你可以看到 16
在 after publish 4
之前被打印出来了。这意味着 squares
goroutine 在主 goroutine 可以开始打印信息之前从通道读取并打印正方形。当主 goroutine 尝试打印通道的长度时,4
已经消失了。
同理,发送5
到channel后,squares
goroutine已经收到了,但是还没有打印出来。它在打印之前被打断了。这意味着频道又是空的,但我们还没有看到25
。
如果您多次 运行 您的示例,您会看到不同的输出。有时 squares
goroutine 会一直运行到 64
,有时则不会。这是完全正常的。在普通代码中,你需要确保在退出之前等待数据被消费,并且你不会依赖于不同goroutines的执行顺序或时间。