【问题标题】:Im learning Go channels and I don't know how to implement this program我正在学习 Go 频道,但我不知道如何实现这个程序
【发布时间】:2021-03-05 08:43:11
【问题描述】:

假设我有 2 个通道发送器,它们正在向一个通道接收器发送数字。第一个通道发送器从 0 发送数字,另一个通道发送器从 11 发送数字。通道接收器接收数据并将其发送到 2 个通道打印机之一。第一个通道打印机接收偶数,另一个接收奇数。打印机应存储数字并在工作完成后打印数据。当通道接收器接收到 20 个数字并将其发送到打印机时,工作应该结束。

var count = 0
func main() {

sender1 := make(chan int)
sender2 := make(chan int)

x := 0
y := 11
for x <= 20{
        var numx = x
        x++
        var numy = y
        y++
        go sender(sender1, numx)
        go sender(sender2, numy)
    }
}
func sender(receiver chan<- int, x int) {
if count >= 20 {
    fmt.Println("limit has been reached")
}
count++
receiver <- x
//even, else odd
if x % 2 == 0{
    fmt.Println("even")
} else {
    fmt.Println("odd")
}
}

这就是我到目前为止所得到的,我不知道下一步该做什么以及如何处理这种情况。

【问题讨论】:

  • 1) 声明您的频道加一个以识别完整性 2) 将您的数据发送给他们sender1 &lt;- numx。 3) 将其包装在一个 goroutine go func(){ //loop sending data to channels close(complete)}() 4) 使用 for select 读取数据。 5)关闭你的频道,像这样play.golang.com/p/QZ3yhPkGyZj

标签: go goroutine channels


【解决方案1】:

所以,如果我正确地解释了你的程序,这个程序应该可以工作。

所以,有两个发件人:

  • 发件人 1 发送:0、1、2、...
  • 发件人 2 发送:11、12、13、...

发送方现在将其发送给接收方,接收方总共监听 20 个数字然后停止(指示发送方和接收方也停止)。

接收者有责任将从发送者 goroutine 接收到的数据中继到打印机。

有两台打印机:

  • 打印机 1 接收奇数并打印出来
  • 打印机 2 接收偶数并打印出来
sender (2 instance) -> mediator (1 instance) -> printer (2 instance)
package main

import (
    "fmt"
    "sync"
)

type packet struct {
    send     chan int
    recvOdd  chan int
    recvEven chan int
    closed   chan struct{}
}

func safeClose(ch chan int) {
    _, ok := <-ch
    if !ok {
        return
    }
    close(ch)
}

// sender spawns multiple goroutines and keeps on
// sending numbers continuously in serial order until
// p.closed is closed. The goroutines have their own
// starting point.
// Example start = [0, 11]
// sender will send it in this order:
// go -> 0, 1, 2, 3 ...  // "go" keyword means goroutine
// go -> 11, 12, 13, ... // "go" keyword means goroutine
func (p *packet) sender(wg *sync.WaitGroup, start ...int) {
    wg.Add(len(start))
    for _, sp := range start {
        // Spawn!
        go func(s int, w *sync.WaitGroup) {
            defer w.Done()
            // Start from "s", keep on incrementing
            for num := s; ; num++ {
                select {
                // I'm done. Return
                case <-p.closed:
                    return
                // Send
                case p.send <- num:
                }
            }
        }(sp, wg)
    }
}

// mediator receives upto a limit and then
// signals to close down. It also judges
// if the number received is even/ odd and
// sends to the respective channel.
func (p *packet) mediator(limit int) {
    for i := 1; i <= limit; i++ {
        r := <-p.send
        if r%2 == 0 {
            p.recvEven <- r
        } else {
            p.recvOdd <- r
        }
    }
    // close down the channels.
    p.close()
}

// close all channels except the send channel
// as there's a possibility that that send's goroutines
// might send to the closed channel which would cause panic.
// So, let send close the p.send channel.
func (p *packet) close() {
    close(p.closed)
    close(p.recvOdd)
    close(p.recvEven)
}

// printer receives from printer
// and then stores it and prints it.
func (p *packet) printer() {
    var odd, even = make(chan []int), make(chan []int)
    go recv(odd, p.recvOdd)
    go recv(even, p.recvEven)
    oBuf, eBuf := <-odd, <-even
    fmt.Println(oBuf)
    fmt.Println(eBuf)
}

// recv just receives and keeps on bufferring.
// When finished receiving, it sends the buffer
// to res.
func recv(res chan<- []int, ch <-chan int) {
    var buffer = make([]int, 0)
    for c := range ch {
        buffer = append(buffer, c)
    }
    res <- buffer
}

func main() {
    // Declare and init a packet
    var p packet
    {
        p.closed = make(chan struct{})
        p.send = make(chan int, 1)
        p.recvEven = make(chan int, 1)
        p.recvOdd = make(chan int, 1)
    }
    defer close(p.send)

    var wg sync.WaitGroup
    defer wg.Wait()

    // Setup a sender which sends values to the mediator.
    // Internally it'll spawn two goroutines. One starts from 0,
    // and the other from 11. Could be extended as well.
    p.sender(&wg, 0, 11)
    // Setup a mediator that mediates the data from sender
    // to printer. Only sends 20 number of data.
    go p.mediator(20)
    // Wait for the printer to print and then return.
    p.printer()
}

【讨论】:

    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2018-12-21
    • 2021-03-27
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多