Go 如何编写更好的双通道选择
在下面的代码中有两个包含工作的通道A和B,在实际代码中,它们是不同的结构,工作人员需要在退出之前排空这两个通道。工人们需要来自两个渠道的信息。这两个select语句可以工作,但非常笨拙。如果我添加Go 如何编写更好的双通道选择,go,goroutine,Go,Goroutine,在下面的代码中有两个包含工作的通道A和B,在实际代码中,它们是不同的结构,工作人员需要在退出之前排空这两个通道。工人们需要来自两个渠道的信息。这两个select语句可以工作,但非常笨拙。如果我添加default:使它们不阻塞,那么代码将无法排空通道。有没有更好的方法来编写选择 现在如果通道A没有工作,那么通道B也不能得到服务。还有一个问题要解决,但不是我最关心的 用于测试以下代码: package main import ( "fmt" "time" ) const (
default:
使它们不阻塞,那么代码将无法排空通道。有没有更好的方法来编写选择
现在如果通道A没有工作,那么通道B也不能得到服务。还有一个问题要解决,但不是我最关心的
用于测试以下代码:
package main
import (
"fmt"
"time"
)
const (
fillCount = 10 // number of elements in each input channel
numWorkers = 3 // number of consumers.
)
func Wait() {
time.Sleep(2000 * time.Millisecond)
}
func fillChannel(work chan string, name string) {
for i := 0; i < fillCount; i++ {
work <- fmt.Sprintf("%s%d", name, i)
}
close(work) // we're finished
}
func doWork(id int, ch1 chan string, ch2 chan string, done chan bool) {
fmt.Println("Running worker", id)
defer fmt.Println("Ending worker", id)
for ch1Open, ch2Open := true, true; ch1Open && ch2Open; {
cnt1 := len(ch1)
cnt2 := len(ch2)
if ch1Open {
select {
case str, more := <-ch1:
if more {
fmt.Printf("%d: ch1(%d) %s\n", id, cnt1, str)
} else {
fmt.Printf("%d: ch1 closed\n", id)
ch1Open = false
}
}
}
if ch2Open {
select {
case str, more := <-ch2:
if more {
fmt.Printf("%d: ch2(%d) %s\n", id, cnt2, str)
} else {
fmt.Printf("%d: ch2 closed\n", id)
ch2Open = false
}
}
}
}
done <- true
}
func main() {
a := make(chan string, 2) // a small channel
b := make(chan string, 5) // a bigger channel
// generate work
go fillChannel(a, "A")
go fillChannel(b, "B")
// launch the consumers
done := make(chan bool)
for i := 0; i < numWorkers; i++ {
go doWork(i, a, b, done)
}
// wait for the goroutines to finish.
for i := 0; i < numWorkers; i++ {
<-done
}
fmt.Println("All workers done.")
Wait() // without this the defered prints from the workers doesn't flush
}
主程序包
进口(
“fmt”
“时间”
)
常数(
fillCount=10//每个输入通道中的元素数
numWorkers=3//消费者数量。
)
func Wait(){
时间。睡眠(2000*时间。毫秒)
}
func fillChannel(工作字符串、名称字符串){
对于i:=0;i 在循环中的两个通道上工作选择。当一个通道关闭时,将通道变量设置为nil以使该通道上的接收未就绪。当两个通道均为nil时,中断循环
主程序包
进口(
“fmt”
“时间”
)
常数(
fillCount=10//每个输入通道中的元素数
numWorkers=3//消费者数量。
)
func fillChannel(工作字符串、名称字符串){
对于i:=0;i 谢谢,这就是我想要的,比我的代码好得多。
package main
import (
"fmt"
"time"
)
const (
fillCount = 10 // number of elements in each input channel
numWorkers = 3 // number of consumers.
)
func fillChannel(work chan string, name string) {
for i := 0; i < fillCount; i++ {
work <- fmt.Sprintf("%s%d", name, i)
}
close(work) // we're finished
}
func doWork(id int, ch1 chan string, ch2 chan string, done chan bool) {
fmt.Println("Running worker", id)
for ch1 != nil || ch2 != nil {
select {
case str, ok := <-ch1:
if ok {
fmt.Printf("%d: ch1(%d) %s\n", id, len(ch1), str)
} else {
ch1 = nil
fmt.Printf("%d: ch1 closed\n", id)
}
case str, ok := <-ch2:
if ok {
fmt.Printf("%d: ch2(%d) %s\n", id, len(ch2), str)
} else {
ch2 = nil
fmt.Printf("%d: ch2 closed\n", id)
}
}
}
fmt.Println("Ending worker", id)
done <- true
}
func main() {
a := make(chan string, 2) // a small channel
b := make(chan string, 5) // a bigger channel
// generate work
go fillChannel(a, "A")
go fillChannel(b, "B")
// launch the consumers
done := make(chan bool)
for i := 0; i < numWorkers; i++ {
go doWork(i, a, b, done)
}
// wait for the goroutines to finish.
for i := 0; i < numWorkers; i++ {
<-done
}
fmt.Println("All workers done.")
}