Схема отмены в Голанге - PullRequest
       15

Схема отмены в Голанге

0 голосов
/ 07 января 2019

Вот цитата из 50 Shades Of Go: ловушки, ошибки и распространенные ошибки :

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

func First(query string, replicas ...Search) Result {  
    c := make(chan Result)
    done := make(chan struct{})
    defer close(done)
    searchReplica := func(i int) { 
        select {
        case c <- replicas[i](query):
        case <- done:
        }
    }
    for i := range replicas {
        go searchReplica(i)
    }

    return <-c
}

Насколько мы понимаем, это означает, что мы используем канал done для прерывания рабочих раньше времени, не ожидая полного выполнения (в нашем случае выполнение replicas[i](query). Следовательно, мы можем получить результат от самого быстрого рабочего («Шаблон первых выигрышей»), а затем отмените работу у всех остальных работников и сохраните ресурсы.

С другой стороны, согласно спецификации :

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

Насколько я понимаю, это означает, что мы не можем interrupt the workers, так как в любом случае все работники оценят функцию replicas[i]query и только затем выберут case <- done и завершат свое выполнение.

Не могли бы вы указать на ошибку в моих рассуждениях?

1 Ответ

0 голосов
/ 07 января 2019

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

Как правило, вы не можете прерывать любую процедуру снаружи, сама программа должна поддерживать какое-то завершение (например, канал отключения, context.Context и т. Д.). См. Отмена операции блокировки в Go .

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

Что происходит с остальными? Остальные будут отброшены (будет выбран case <- done, так как небуферизованный канал не может содержать никаких элементов, и больше никто не будет получать больше от канала).

Вы можете проверить это в этом примере Go Playground .

...