Чтение из канала Golang

Рейтинг: 1Ответов: 1Опубликовано: 20.02.2023

Код работает. Но я не понимаю почему он работает в целом, если у меня есть два канала на чтение из select, но нигде нет ни одного канала на запись (или буфера откуда будет происходить чтение).

Я понимаю, что time.After и Done() возвращают значения типа chan, но разве у меня горутина не станет в очередь, ибо на запись ничего нет (и буфера также)?

package main

import (
    "context"
    "fmt"
    "time"
)

const shortDuration = 500 * time.Millisecond

func main() {
    d := time.Now().Add(shortDuration)
    ctx, cancel := context.WithDeadline(context.Background(), d)

    if cancel != nil {
        ctx.Err()
    }

    select {
    case <-time.After(1 * time.Second):
        fmt.Println("overslept")
    case <-ctx.Done():
        fmt.Println(ctx.Err())
    }
}

Ответы

▲ 2Принят

Что вы ожидали? select блокируется, пока один из каналов не станет активным.

Канал time.After должен активироваться через секунду, а канал ctx.Done через полсекунды (значение shortDuration). У вас происходит событие в канале ctx.Done, select срабатывает и программа завершается.

В каналы ctx.Done и time.After пишет системная горутина, которая отвечает за обработку событий таймера. Пока горутина main ждёт события в select, в системной горутине тикает таймер. Первым натикивает дедлайн контекста. Если вы зададите shortDuration длиннее одной секунды, то первым будет срабатывать таймер ctx.After

Кстати, зачем вы проверяете cancel? Эта функция для контекста с таймаутом никогда не nil, можно не волноваться.