Я следую https://blog.golang.org/pipelines, чтобы выполнить несколько этапов.

Мне нужен один из этапов, чтобы ввести задержку в несколько секунд, прежде чем события будут переданы на следующем этапе в конвейере.

Моя проблема с приведенным ниже кодом заключается в том, что он выдаст неограниченное количество подпрограмм go в этот раз. Перед тем как передать события. Есть ли лучшие способы сделать это?

Спасибо!

func fooStage(inChan <- chan *Bar) (<- chan *Bar) {
    out := make(chan *Bar, 10000)
    go func() {
        defer close(out)
        wg := sync.WaitGroup{}
        for {
            select {
            case event, ok := <-inChan:
                if !ok {
                    // inChan closed
                    break
                }
                wg.Add(1)
                go func() {
                    time.Sleep(5 * time.Second)
                    out <- event
                    wg.Done()
                }()
            }
        }
        wg.Wait()
    }()
    return out
}
0
ultimoo 20 Окт 2017 в 21:08

3 ответа

Лучший ответ

Вы можете использовать другой канал, чтобы ограничить количество активных подпрограмм, которые может создать ваш цикл.

const numRoutines = 10

func fooStage(inChan <-chan *Bar) <-chan *Bar {
    out := make(chan *Bar, 10000)
    routines := make(chan struct{}, numRoutines)
    go func() {
        defer close(out)
        wg := sync.WaitGroup{}
        for {
            select {
            case event, ok := <-inChan:
                if !ok {
                    // inChan closed
                    break
                }
                wg.Add(1)
                routines <- struct{}{}
                go func() {
                    time.Sleep(5 * time.Second)
                    out <- event
                    wg.Done()
                    <-routines
                }()
            }
        }
        wg.Wait()
    }()
    return out
}
1
RayfenWindspear 20 Окт 2017 в 18:37

Вы можете исправить количество горутин вручную - начиная только с нужного вам числа.

func sleepStage(in <-chan *Bar) (out <-chan *Bar) {
     out = make(<-chan *Bar)
     wg := sync.WaitGroup
     for i:=0; i < N; i++ {  // Number of goroutines in parallel
           wg.Add(1)
           go func(){
                defer wg.Done()
                for e := range in {
                    time.Sleep(5*time.Seconds)
                    out <- e
                }
            }()
      }
      go func(){}
           wg.Wait()
           close(out)
       }()
       return out
  }
1
Eugene Lisitsky 21 Окт 2017 в 07:20

Вы можете использовать time.Ticker:

func fooStage(inChan <- chan *Bar) (<- chan *Bar) {
    //... some code
    ticker := time.NewTicker(5 * time.Second)
    <-ticker // the delay, probably need to call twice
    ticker.Stop()
    close(ticker.C)
    //... rest code
}
0
Alexander Trakhimenok 20 Окт 2017 в 22:15