Golang: коммуникация каналов с воркерами

Beginner

This tutorial is from open-source community. Access the source code

Введение

В Golang закрытие канала может использоваться для передачи сигнала о завершении работы приемникам канала. В этом практическом задании будет показано, как использовать канал для передачи задач от горутины main() к воркеру, и как закрывать канал, когда у воркера больше нет задач.

Закрытие каналов

В этом практическом задании вам нужно изменить заданный код, чтобы закрыть канал jobs, когда у воркера больше нет задач. Также вам нужно использовать канал done для уведомления о том, когда все задачи будут выполнены.

  • Используйте буферизованный канал jobs для передачи задач от горутины main() к воркеру.
  • Используйте канал done для уведомления о том, когда все задачи будут выполнены.
  • Используйте воркера-горутину для повторного приема из jobs с использованием j, more := <-jobs.
  • Используйте специальный двухзначный вид приема для уведомления по каналу done, когда все задачи будут выполнены.
  • Отправьте 3 задачи в воркера по каналу jobs, а затем закройте его.
  • Используйте подход синхронизации, чтобы дождаться завершения работы воркера.
$ go run closing-channels.go
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs

## The idea of closed channels leads naturally to our next
## example: `range` over channels.

Ниже представлен полный код:

// _Закрытие_ канала означает, что больше не будут
// отправляться значения. Это может быть полезно для
// передачи сигнала о завершении работе приемникам канала.

package main

import "fmt"

// В этом примере мы будем использовать канал `jobs` для
// передачи задач от горутины `main()` к воркеру. Когда
// у воркера больше нет задач, мы закроем канал `jobs`.
func main() {
    jobs := make(chan int, 5)
    done := make(chan bool)

    // Вот воркера-горутина. Она повторно получает из
    // `jobs` с использованием `j, more := <-jobs`. В этом
    // специальном двухзначном виде приема значение `more`
    // будет `false`, если канал `jobs` был `закрыт`, и все
    // значения из канала уже были получены. Мы используем
    // это для уведомления по каналу `done`, когда мы
    // обработаем все наши задачи.
    go func() {
        for {
            j, more := <-jobs
            if more {
                fmt.Println("received job", j)
            } else {
                fmt.Println("received all jobs")
                done <- true
                return
            }
        }
    }()

    // Это отправляет 3 задачи в воркера по каналу `jobs`,
    // а затем закрывает его.
    for j := 1; j <= 3; j++ {
        jobs <- j
        fmt.Println("sent job", j)
    }
    close(jobs)
    fmt.Println("sent all jobs")

    // Мы дожидаемся завершения работы воркера с
    // использованием подхода [синхронизации](channel-synchronization),
    // который мы видели ранее.
    <-done
}

Резюме

В этом практическом задании вы узнали, как использовать канал для передачи задач от горутины main() к воркеру, и как закрывать канал, когда у воркера больше нет задач. Также вы узнали, как использовать канал done для уведомления о том, когда все задачи будут выполнены.