亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

是否可以在處理時將項目添加到 Go 通道?

是否可以在處理時將項目添加到 Go 通道?

Go
慕容708150 2022-06-01 09:50:48
我正在嘗試找到一種方法來使用 goroutine 遞歸地完成 Go 中的任務。該程序的目標是將輸入元素放入通道并添加到輸出通道輸入 -1 直到達到 0。處理的工人數量應該是可適應的。我遵循的過程是這樣的:創建一個輸入輸出通道。將起始編號添加到輸入通道。初始化workers以運行worker函數。循環并打印輸出通道中的輸出。func main() {    inputChannel := make(chan int, 1)    outputChannel := make(chan int)    inputChannel <- 100    numWorkers := 4    for i := 0; i < numWorkers; i++ {        go worker(inputChannel, outputChannel)    }    for elem := range outputChannel {        fmt.Println("Output: ", elem)    }}接下來,在 order 函數中,我們遍歷輸入通道中的元素,每次檢查是否有更多元素要接收。如果有更多元素要接收,我們打印輸入元素,從元素中減去 1,如果元素大于 0,則發送到輸入通道以供另一個工作人員拾取。如果輸入通道中沒有任何內容,那么我們返回。func worker(input chan int, output chan<- int) {    defer close(input)    defer close(output)    for {        element, more := <-input        if more {            fmt.Println("Input: ", element)            element--            if element != 0 {                input <- element            }        } else {            fmt.Println("All Jobs Processed")            return        }    }}我看到的輸出是:Input:  100Input:  99Input:  98Input:  97Input:  96Input:  95Input:  94Input:  93Input:  92Input:  91Input:  90Input:  89Input:  88Input:  87Input:  86Input:  85Input:  84Input:  83Input:  82Input:  81Input:  80Input:  79Input:  78Input:  77Input:  76Input:  75Input:  74Input:  73Input:  72Input:  71Input:  70Input:  69Input:  68Input:  67Input:  66Input:  65Input:  64Input:  63Input:  62Input:  61Input:  60Input:  59Input:  58Input:  57Input:  56Input:  55Input:  54Input:  53Input:  52Input:  51Input:  50Input:  49Input:  48Input:  47Input:  46Input:  45Input:  44Input:  43Input:  42Input:  41Input:  40Input:  39Input:  38Input:  37Input:  36Input:  35Input:  34Input:  33Input:  32Input:  31Input:  30Input:  29Input:  28Input:  27Input:  26Input:  25Input:  24Input:  23Input:  22Input:  21Input:  20Input:  19Input:  18Input:  17Input:  16Input:  15Input:  14我已經以多種方式嘗試了這一點,依賴于這樣的渠道并使用等待組,但我似乎無法讓流程處理所有項目并發出輸出。
查看完整描述

1 回答

?
猛跑小豬

TA貢獻1858條經驗 獲得超8個贊

好的,我們開始吧。首先,請注意您的代碼中存在一些問題。然后修復它們。


正如Adrian所說,從已經關閉或沒有元素的通道中讀取。在您的工作人員功能中,您正在這樣做。當您在另一個工作人員關閉輸入通道后從輸入通道讀取元素時,就會發生這種情況。


func worker(input chan int, output chan<- int) {

    defer close(input)

    ...

    for {

        element, more := <-input

        ...

    }

}

那么,為什么在所有工作人員完成后不關閉輸入通道?


在解決了輸入通道的問題后,當您嘗試從輸出通道讀取時,會出現另一個問題。此外,您不會在輸出通道上發送任何內容。如果您不需要該頻道,那么為什么要使用該頻道。而且這個輸出通道是無緩沖的(大小為0的通道和發送接收應該同時,否則會出現死鎖情況)??矗瑥倪@里和這里緩沖與無緩沖。也許網絡上有更多有用的文檔。感謝我的朋友Nightfury1204從他的這篇文章中獲得了關于緩沖與非緩沖頻道的第一個鏈接。


outputChannel := make(chan int) // unbuffered, no size is defined

...

for elem := range outputChannel {

    fmt.Println("Output: ", elem)

}

所以,如果你想向輸出通道發送一些東西,那么邏輯是你自己的。例如,您可以在工作人員中完成輸入通道處理后發送一些內容。在這種情況下,將您的輸出通道聲明為長度為 4 的緩沖通道(因為您正在運行 4 個工作人員)。完成所有工作人員后,關閉您的輸出通道,然后閱讀。


outputChannel := make(chan int, 4) // buffered

...

// after finishing all your workers

close(outputChannel)

for elem := range outputChannel {

    fmt.Println("Output: ", elem)

}

需要注意的是,使用sync.WaitGroupfrom "sync"package 來等待一組 goroutine 完成。


請參見下面的示例:https: //play.golang.org/p/WAqwyR0ggNN


import "fmt"

import "sync"


func main() {

    inputChannel := make(chan int, 1)

    outputChannel := make(chan int, 4)


    var wg sync.WaitGroup

    wg.Add(4)


    inputChannel <- 100

    numWorkers := 4

    for i := 0; i < numWorkers; i++ {

        go func() {

            defer wg.Done()

            for {

                select {

                case element := <-inputChannel:

                    fmt.Println("Input: ", element)

                    element--

                    if element != 0 {

                        inputChannel <- element

                    }

                default:

                    outputChannel<-0

                    fmt.Println("All Jobs Processed", len(outputChannel))

                    return

                }

            }

        }()

    }

    wg.Wait()

    close(inputChannel)

    close(outputChannel)

    for elem := range outputChannel {

        fmt.Println("Output: ", elem)

    }

}


查看完整回答
反對 回復 2022-06-01
  • 1 回答
  • 0 關注
  • 122 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號