Материал проходит вычитку — возможны неточности.
Урок 113 из 118

merge с отменой и пайплайн

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

Главная мысль

наивный merge утекает, если читатель уходит раньше времени; done/ctx лишь сигналит передатчикам merge — они завершаются сами, а горутины, питающие входные каналы, обязаны слушать отмену отдельно.

Утечка наивного merge

func merge(chs ...<-chan *FileMeta) <-chan *FileMeta { /* наивная версия из L93 */ }

out := merge(a, b, c)
v := <-out
// читатель взял одно значение и ушёл

Передатчики заблокированы на out <- v: никто больше не читает. Они висят вечно — это утечки горутин из. Наивный merge корректен, только если читатель дочитывает до конца.

Отмена в двух уровнях

func merge(done <-chan struct{}, chs ...<-chan *FileMeta) <-chan *FileMeta {
    out := make(chan *FileMeta)
    var wg sync.WaitGroup

    for _, ch := range chs {
        wg.Add(1)
        go func(ch <-chan *FileMeta) {
            defer wg.Done()
            for {
                select {
                case v, ok := <-ch:
                    if !ok {
                        return
                    }
                    select {
                    case out <- v:
                    case <-done:
                        return
                    }
                case <-done:
                    return
                }
            }
        }(ch)
    }

    go func() {
        wg.Wait()
        close(out)
    }()

    return out
}

Два уровня select: первый — «пришло значение или отмена», второй — «удалось отправить или отмена». Закрыл done — передатчики выходят, WaitGroup досчитывается, out закрывается. Горутины, питающие входные каналы, тоже должны уметь отменяться — сигнал через ctx или тот же done.

Пайплайн из стадий

Каждая стадия пайплайна — функция «канал в, канал наружу»: square читает числа и возвращает канал квадратов, sum — последняя стадия, читает и складывает. Отмена прокидывается через все стадии одним контекстом. Стадии независимы и проверяемы по отдельности.

В следующем уроке

Вы узнаете:

  • как передаются ошибки по пайплайну
  • кто закрывает выходной канал пайплайна
<!-- wp:course-hub/quiz {"title":"Проверьте себя","questions":[{"text":"Читатель наивного merge прочитал одно значение и ушёл. Что с передатчиками?","options":[{"text":"Блокируются на out
Итоги

Наивный merge утекает без читателя; done/ctx в двух уровнях select сворачивают передатчики, но входные горутины должны слушать отмену сами; стадии пайплайна соединяются каналами и делят одну отмену.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки