Как выбрать ожидание блока при работе ctx.Done ()? - PullRequest
0 голосов
/ 17 июня 2020

В приведенном ниже коде:

    ctx, cancel := context.WithTimeout(req.Context(), 5000*time.Second)

    // Wait for the response or timeout
    select {
    case <-ctx.Done():
        log.Println("timeout, cancel work...")

        // Cancel the request and wait for it to complete
        // this will shutdown the go-routine immediately
        tr.CancelRequest(req)
        log.Println(<-ch)

    case err := <-ch:
        // do something
    }

select ожидает двух операций приема одновременно. Одна операция приема (<-ch) является блочной операцией

Среди выполнения блока select Is ctx.Done() вызывается более одного раза в блоке select, чтобы проверить, возвращает ли ctx.Done() канал ? пока <-ch не заблокируется ...

Ответы [ 2 ]

1 голос
/ 17 июня 2020

Spe c: Операторы выбора:

Для всех случаев в операторе операнды каналов операций приема, а также выражения канала и правой части операторов отправки оцениваются только один раз в исходном порядке при вводе оператора "select".

select звонит ctx.Done() только один раз. Он возвращает канал, и операция приема из этого канала отслеживается, если она может продолжаться.

Если время ожидания 5000*time.Second истекло, или если родительский контекст (req.Context()) отменен (например, истекло время ожидания или вызывается его функция cancel()), то канал, который был возвращен ctx.Done(), будет закрыт, поэтому прием от него может продолжаться (это больше не будет операцией блокировки). Spe c: Оператор приема:

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

0 голосов
/ 17 июня 2020

Обычно, когда вы используете блокирующий канал и функцию тайм-аута, вы можете поместить его в поле выбора l oop.

ctx, cancel := context.WithTimeout(req.Context(), 5000*time.Second)

    // Wait for the response or timeout
   for {
    select {
    case <-ctx.Done():
        log.Println("timeout, cancel work...")

        // Cancel the request and wait for it to complete
        // this will shutdown the go-routine immediately
        tr.CancelRequest(req)
        log.Println(<-ch)
        break
    case err := <-ch:
        // do something
        break
    }
   }

В этом случае <-ch больше не блокирует и избранный вызывает ctx.Done() более одного раза. Если вы не используете for-l oop, ctx.Done() вызывается только один раз (как уже указывал @icza)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...