[英]golang: channel in select statement is only receiving sometimes (???)
[英]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個工人之一承擔...
現在,希望您對我的第一個代碼有更好的理解。 但是在我的代碼中,我從來沒有涉及第二種情況。
您的quitIn
和quitOut
通道基本上是無用的:創建它們並嘗試從中接收。 您無法做到這一點,因為沒有人可以寫這些頻道,因為沒人知道它們的存在。 我不能多說,因為我不明白代碼應該做什么。
我認為您的解決方案可能有點復雜。 這是一個簡化的版本。 謹記有很多實現。 一篇不錯的文章
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.