簡體   English   中英

選擇中的Golang頻道未收到

[英]Golang channel in select not receiving

我目前正在編寫一個小的腳本,在其中使用通道,select和goroutine,但我真的不明白為什么它不按我的想法運行。

我有2個頻道,所有我的goroutine都收聽。

我將通道傳遞給每個goroutine,每個goroutine都有一個選擇,必須根據數據的先后順序在2個之間進行選擇。

問題在於,沒有goroutine屬於第二種情況。 我可以一個接一個地收到100個工作,我在日志中看到了所有內容。 在第一種情況下,它做得很好,然后在第二個通道中發送了工作(即使做得很好……),我沒有更多的日志了。 我只是不明白為什么...

如果有人能啟發我:)

package main

func main() {

    wg := new(sync.WaitGroup)
    in := make(chan *Job)
    out := make(chan *Job)
    results := make(chan *Job)

    for i := 0; i < 50; i++ {
        go work(wg, in, out, results)
    }

    wg.Wait()

    // Finally we collect all the results of the work.
    for elem := range results {
            fmt.Println(elem)
    }    
}

func Work(wg *sync.WaitGroup, in chan *Job, out chan *Job, results chan *Job) {
    wg.Add(1)
    defer wg.Done()
    for {
        select {
        case job := <-in:
            ticker := time.Tick(10 * time.Second)

            select {
            case <-ticker:
                // DO stuff
            if condition is true {
                out <- job
            }
            case <-time.After(5 * time.Minute):
                fmt.Println("Timeout")
            }
        case job := <-out:
            ticker := time.Tick(1 * time.Minute)

            select {
            case <-ticker:
                // DO stuff
            if condition is true {
                results <- job
            }

            case <-quitOut:
                fmt.Println("Job completed")
            }
        }
    }
}

我創建了一些工作人員,他們收聽2個頻道並將最終結果發送到第3個頻道。

它對接收到的作業進行某些操作,如果它驗證了給定的條件,則將該作業傳遞到下一個通道,如果它驗證了條件,則將作業傳遞到結果通道。

因此,在我的腦海中,例如,有一個供5個工作人員使用的管道:在通道IN中有3個工作,直接有3個工作人員接他們,如果這3個工作驗證了條件,則在通道OUT中發送它們。 直接有2個工人接他們,第3個工作由前3個工人之一承擔...

現在,希望您對我的第一個代碼有更好的理解。 但是在我的代碼中,我從來沒有涉及第二種情況。

您的quitInquitOut通道基本上是無用的:創建它們並嘗試從中接收。 您無法做到這一點,因為沒有人可以寫這些頻道,因為沒人知道它們的存在。 我不能多說,因為我不明白代碼應該做什么。

我認為您的解決方案可能有點復雜。 這是一個簡化的版本。 謹記有很多實現。 一篇不錯的文章

https://medium.com/smsjunk/handling-1-million-requests-per-minute-with-golang-f70ac505fcaa

甚至可以從Go手冊中獲得更好的選擇

https://gobyexample.com/worker-pools (我認為這可能是您的目標)

無論如何,下面是不同類型的示例。有幾種解決此問題的方法。

package main

import (
    "context"
    "log"
    "os"
    "sync"
    "time"
)

type worker struct {
    wg   *sync.WaitGroup
    in   chan job
    quit context.Context
}

type job struct {
    message int
}

func main() {
    numberOfJobs := 50

    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    w := worker{
        wg:   &sync.WaitGroup{},
        in:   make(chan job),
        quit: ctx,
    }

    for i := 0; i < numberOfJobs; i++ {
        go func(i int) {
            w.in <- job{message: i}
        }(i)
    }

    counter := 0
    for {
        select {
        case j := <-w.in:
            counter++
            log.Printf("Received job %+v\n", j)
            // DO SOMETHING WITH THE RECEIVED JOB
            // WORKING ON IT
            x := j.message * j.message
            log.Printf("job processed, result %d", x)
        case <-w.quit.Done():
            log.Printf("Recieved quit, timeout reached.  Number of jobs queued: %d, Number of jobs complete: %d\n", numberOfJobs, counter)
            os.Exit(0)
        default:
            // TODO
        }
    }

}

因為您的功能是“工作”,而您正在調用“工作”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM