我正在学习使用Go频道,并且总是陷入僵局。此代码可能有什么问题?当阵列大小不相等时,打印机会随机停止工作;我想这将有助于以某种方式通知打印机接收器停止工作。任何想法如何解决?我的代码粘贴在下面。
package main
import (
"fmt"
"sync"
)
var wg = sync.WaitGroup{}
var wgs = sync.WaitGroup{}
var sg = make(chan int, 50)
var gp1 = make(chan int, 50)
var gp2 = make(chan int, 50)
func main(){
wgs.Add(2)
go Sender(0)
go Sender(11)
wg.Add(3)
go Receiver()
go Printer()
go Printer2()
wg.Wait()
}
func Sender(start int){
defer wgs.Done()
for i := start; i < 20; i++ {
sg <- i
}
}
func Receiver(){
defer wg.Done()
for i := 0; i < 20; i++{
nr := <- sg
if nr % 2 == 0{
gp1 <- nr
} else{
gp2 <- nr
}
}
}
func Printer(){
defer wg.Done()
var m [10]int
for i := 0; i < 10; i++ {
m[i] = <- gp1
}
wgs.Wait()
fmt.Println(m)
}
func Printer2(){
defer wg.Done()
var m [10]int
for i := 0; i < 10; i++ {
m[i] = <- gp2
}
wgs.Wait()
fmt.Println(m)
}
// Better to use this one
// func Receiver(senderChannel <-chan int, printerChannel1 chan<- int, printerChannel2 chan<- int, wg *sync.WaitGroup) {
答案 0 :(得分:0)
发件人生成(我认为有28条消息)。前20个中的大约一半分配给gp1和gp2中的一个。然后Printer和Printer2卸载消息
问题是,接收方拆分邮件的方式取决于接收到的数字是奇数还是偶数。但是您并没有为此而控制。如果其中一台打印机的队列中的物品少于10件,它将挂起
那是一个潜在的问题
答案 1 :(得分:0)
您的核心问题是,其中的所有内容都是“错误的推算”:他们希望看到固定数量的消息,但这不一定与现实相符。您应该设置通道,以便一旦产生所有数据就将其关闭。
这可能意味着设置一个中间功能来管理发送:
func Sender(from, to int, c chan<- int) {
for i := from; i < to; i++ {
c <- i
}
}
func SendEverything(c chan<- int) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
Sender(0, 20, c)
}()
go func() {
defer wg.Done()
Sender(11, 20, c)
}()
wg.Wait()
close(c)
}
使调度程序功能可在通道中的所有功能上工作:
func Receive(c <-chan int, odds, evens chan<- int) {
for n := range c {
if n%2 == 0 {
evens <- n
} else {
odds <- n
}
}
close(odds)
close(evens)
}
然后您可以共享一个打印功能:
func Printer(prefix string, c <-chan int) {
for n := range c {
fmt.Printf("%s: %d\n", prefix, n)
}
}
最后,您有一个将所有功能缝合在一起的主要功能:
func main() {
var wg sync.WaitGroup
inputs := make(chan int)
odds := make(chan int)
evens := make(chan int)
wg.Add(4)
go func() {
defer wg.Done()
SendEverything(inputs)
}()
go func() {
defer wg.Done()
Receive(inputs, odds, evens)
}()
go func() {
defer wg.Done()
Printer("odd number", odds)
}()
go func() {
defer wg.Done()
Printer("even number", evens)
}()
wg.Wait()
}
完整的示例在https://play.golang.org/p/qTUqlt-uaWH。
请注意,我完全避免使用任何全局变量,并且任何东西都希望有一个不言自明的非常短的名称(i
和n
是简单的整数,c
是频道)或完整的单词(odds
,evens
)。我倾向于将sync.WaitGroup
对象保留在其创建位置的本地。由于所有内容都是作为参数传递的,因此我不需要同一个函数的两个副本来作用于不同的全局变量,并且如果我选择为此编写测试代码,则可以创建自己的本地通道。