英文:
why I can not see output when received value by channel
问题
在下一个示例中,我不明白为什么在接收到时没有打印出 end 值。
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 来解决这个问题。
英文:
in the next example, I don't understand why end value not printed when received
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
}
I know sync.WaitGroup can solve this problem.
答案1
得分: 1
因为程序在到达func main
的结尾时退出,而不管是否有其他goroutine正在运行。一旦第二个函数从end
通道接收到数据,main函数对该通道的发送操作将被解除阻塞,程序将在将接收到的值传递给Println
之前结束。
英文:
Because the program exits when it reaches the end of func main
, regardless of whether any other goroutines are running. As soon as the second function receives from the end
channel, main's send on that channel is unblocked and the program finishes, before the received value gets a chance to be passed to Println
.
答案2
得分: 0
结束值没有被打印出来,因为一旦主goroutine(实际上是main
函数的一个goroutine)完成(换句话说,解除阻塞),其他非主goroutine就没有机会完成。当函数main()
返回时,程序退出。此外,goroutine是独立的执行单元,当一系列goroutine一个接一个地启动时,你不能依赖于goroutine实际启动的顺序。你的代码逻辑必须独立于goroutine调用的顺序。
解决问题的一种方法(在你的情况下最简单的方法)是在main()
函数的末尾加上time.Sleep
。
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
。
英文:
The end value is not printed because as soon as the main
goroutine (the main
function is actually a goroutine) is finished (in other terms get unblocked) the other non-main goroutines does not have the chance to get completed.
When the function main() returns, the program exits. Moreover goroutines are independent units of execution and when a number of them starts one after the other you cannot depend on when a goroutine will actually be started. The logic of your code must be independent of the order in which goroutines are invoked.
One way to solve your problem (and the easiest one in your case) is to put a time.Sleep
at the end of your main()
function.
time.Sleep(1e9)
This will guarantee that the main goroutine will not unblock and the other goroutines will have a change to get executed.
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)
}
Another solution as you mentioned is to use waitgroup
.
答案3
得分: 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("开始")
fmt.Println(<-start)
}()
go func() {
defer wg.Done()
fmt.Println("结束")
fmt.Println(<-end)
}()
start <- 1
end <- 2
wg.Wait()
}
英文:
Apart from sleep where you have to specify the time, you can use waitgroup to make you program wait until the goroutine completes execution.
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论