我想使用多个 go 例程返回 channel 创建一个扇入函数,这是我的代码。
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var wg, wg2 sync.WaitGroup
func main() {
final := talk(boring("Joe"), boring("Ann"))
for i := 0; i < 10; i++ {
fmt.Println(<-final)
}
fmt.Println("You are both boring I'm leaving")
}
func talk(input1, input2 <-chan string) <-chan string {
out := make(chan string)
go func() {
wg.Add(1)
for {
out <- <-input1
}
}()
go func() {
wg.Add(1)
for {
out <- <-input2
}
}()
wg.Done()
close(out)
return out
}
func boring(msg string) <-chan string {
c := make(chan string)
for i := 0; i < 5; i++ {
c <- fmt.Sprintf("%s%d\n", msg, i)
time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
}
return c
}
但是我运行上面的代码后出现错误
all goroutines are asleep - deadlock
我已经尝试关闭 channel ,但它仍然给我错误。我曾尝试将无聊的返回 channel 分配给 Joe 和 Ann,然后将这些 channel 传递给多路复用的通话功能,但仍然没有成功。我是新来学习 channel 的,对这个概念不是很清楚。
最佳答案
代替 WaitGroup ,您可以使用select
:https://tour.golang.org/concurrency/5
The
select
statement lets a goroutine wait on multiple communication operations.A
select
blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
final := talk(boring("Joe"), boring("Ann"))
for i := 0; i < 10; i++ {
fmt.Println(<-final)
}
fmt.Println("You are both boring I'm leaving")
}
func talk(input1, input2 <-chan string) <-chan string {
c := make(chan string)
go func() {
for {
select {
case s := <-input1:
c <- s
case s := <-input2:
c <- s
}
}
}()
return c
}
func boring(msg string) <-chan string {
c := make(chan string)
go func() {
for i := 0; i < 5; i++ {
c <- fmt.Sprintf("%s: %d", msg, i)
time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
}
}()
return c
}
编辑:
在您给出的示例中,boring
函数不使用 goroutine 重复发送 channel ,这将永远阻塞,因为:
https://tour.golang.org/concurrency/2
By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.
此外,wg.Done()
需要成为 goroutine 的一部分。
我通过进行上述更改使其正常工作:https://play.golang.org/p/YN0kfBO6iT
关于Go lang 多路复用所有 goroutines 都睡着了 - 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44487887/