我想创建一个使用多个go例程的扇入函数返回通道这里是我的代码。
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
}
但是在运行代码
之后我遇到了错误所有goroutines都睡着了 - 僵局
我试图关闭频道,但它仍然给我错误。我试图将无聊的返回频道分配给Joe和Ann,然后将这些频道传递给用于多路复用的通话功能仍然没有成功。我是新手,学习这个概念的渠道不明确。
答案 0 :(得分:2)
您可以使用select
:https://tour.golang.org/concurrency/5
select
语句允许goroutine等待多次通信 操作
select
阻塞,直到其中一个案例可以运行,然后执行该案例 案件。如果多个准备就绪,它会随机选择一个。
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重复发送通道,这将永远阻止,因为:
https://tour.golang.org/concurrency/2
默认情况下,发送和接收阻止,直到另一方准备好。 这允许goroutine在没有显式锁定的情况下进行同步 条件变量。
此外,wg.Done()
需要成为goroutine的一部分。
我通过以上更改来实现它:https://play.golang.org/p/YN0kfBO6iT
答案 1 :(得分:1)
你不能单独阻止goroutine,我建议用goroutine发出信号,要求戒掉这些东西:
stop := make(chan bool)
go func() {
for {
select {
case <- stop:
return
default:
// Do other stuff
}
}
}()
// Do stuff
// Quit goroutine
stop<- true