在下一个例子中,我不明白为什么收到
时不打印结束值package main
import "fmt"
func main() {
start := make(chan int)
end := make(chan int)
go func() {
fmt.Println("Start")
fmt.Println(<-start)
}()
go func() {
fmt.Println("End")
fmt.Println(<-end)
}()
start <- 1
end <- 2
}
我知道sync.WaitGroup可以解决这个问题。
答案 0 :(得分:1)
因为程序在到达func main
结束时退出,无论是否有其他goroutine正在运行。一旦第二个功能从end
频道收到,该频道上的主要发送被取消阻止并且程序结束,然后收到的值有机会传递给Println
。 / p>
答案 1 :(得分:0)
不会打印结束值,因为只要main
goroutine(main
函数实际上是goroutine)完成(换句话说取消阻止),其他非主要goroutines就不会打印有机会完成。
当函数main()返回时,程序退出。此外goroutines是独立的执行单元,当它们中的一个一个接一个地启动时,你不能依赖于goroutine实际上何时会开始。代码的逻辑必须独立于调用goroutine的顺序。
解决问题的一种方法(在您的情况下最简单的方法)是在time.Sleep
函数的末尾添加main()
。
time.Sleep(1e9)
这样可以保证主goroutine不会解锁,而其他goroutine会有更改来执行。
package main
import (
"fmt"
"time"
)
func main() {
start := make(chan int)
end := make(chan int)
go func() {
fmt.Println("Start")
fmt.Println(<-start)
}()
go func() {
fmt.Println("End")
fmt.Println(<-end)
}()
start <- 1
end <- 2
time.Sleep(1e9)
}
您提到的另一种解决方案是使用waitgroup
。
答案 2 :(得分:0)
除了必须指定时间的睡眠之外,您可以使用waitgroup让程序等待,直到goroutine完成执行。
package main
import "fmt"
import "sync"
var wg sync.WaitGroup
func main() {
start := make(chan int)
end := make(chan int)
wg.Add(2)
go func() {
defer wg.Done()
fmt.Println("Start")
fmt.Println(<-start)
}()
go func() {
defer wg.Done()
fmt.Println("End")
fmt.Println(<-end)
}()
start <- 1
end <- 2
wg.Wait()
}