icz*_*cza 10
但这非常容易且惯用.该语言提供了手段:渠道类型.
只需将通道传递给函数,并让函数在通道上发送结果而不是返回它们.通道可以安全地同时使用.
在任何给定时间,只有一个goroutine可以访问该值.根据设计,数据竞争不会发生.
示例解决方案
func getA(ch chan int) {
fmt.Println("getA: Calculating...")
time.Sleep(300 * time.Millisecond)
fmt.Println("getA: Done!")
ch <- 100
}
func getB(ch chan int) {
fmt.Println("getB: Calculating...")
time.Sleep(400 * time.Millisecond)
fmt.Println("getB: Done!")
ch <- 200
}
func main() {
cha := make(chan int)
chb := make(chan int)
go getA(cha)
go getB(chb)
C := <-cha + <-chb // waits till getA() and getB() return
fmt.Println("Result:", C)
fmt.Println("All done!")
}
输出(在Go Playground上试试):
getB: Calculating...
getA: Calculating...
getA: Done!
getB: Done!
Result: 300
All done!
注意:
以上示例也可以使用单个通道实现:
func main() {
ch := make(chan int)
go getA(ch)
go getB(ch)
C := <-ch + <-ch // waits till getA() and getB() return
fmt.Println("Result:", C)
fmt.Println("All done!")
}
输出是一样的.在Go Playground上试试这个变种.
在围棋规范规定是这样的函数的返回值被丢弃.更多相关内容:从goroutine返回值会发生什么.
你提出的建议从多处伤口流血.Go中的每个变量都有一个范围(可以在其中引用它们).访问变量不会阻止.语句或运算符的执行可能会阻塞(例如,接收运算符或发送语句).
你的建议:
go A := getA()
go B := getB()
C := A + B // waits till getA() and getB() return
ABgogogogo
C := A + B
ABgogetA()go
b)否则我们需要一些外部代码进行同步,但是我们再也没有获得任何东西(只是使其与通道解决方案相比更糟).
通过使用渠道,很清楚什么(可能)阻止什么不阻止.很明显,当从通道接收完成时,goroutine就完成了.并且它为我们提供了在我们想要时执行接收的意思(在需要它的值并且我们愿意等待它时),以及检查值是否准备好而没有阻塞的意思(逗号成语).