Синхронизация двух горутин с каналом размера 1 - PullRequest
0 голосов
/ 18 июня 2020

Пытаясь узнать golang, я просматривал go источник для обратного прокси:

https://golang.org/src/net/http/httputil/reverseproxy.go

Я нашел этот блок код (усеченный):

...
    errc := make(chan error, 1)
    spc := switchProtocolCopier{user: conn, backend: backConn}
    go spc.copyToBackend(errc)
    go spc.copyFromBackend(errc)
    <-errc
    return
}

// switchProtocolCopier exists so goroutines proxying data back and
// forth have nice names in stacks.
type switchProtocolCopier struct {
    user, backend io.ReadWriter
}


func (c switchProtocolCopier) copyFromBackend(errc chan<- error) {
    _, err := io.Copy(c.user, c.backend)
    errc <- err
}

func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
    _, err := io.Copy(c.backend, c.user)
    errc <- err
}

Фрагмент, который привлек мое внимание, - это создание канала с буферизацией err c. Я подумал (вероятно, наивно), что мы будем использовать небуферизованный канал, и более поздний прием из err c должен будет выполняться дважды, например:

<-errc
<-errc

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

Чего я не понимаю, почему это написано так . Это для того, чтобы гарантировать выполнение только одного из методов? Если это так, не могли бы они оба работать технически?

Спасибо!

1 Ответ

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

Канал размером один помогает реализовать двоичный семафор.

Поскольку из канала потребляется не более одного значения (в строке 549), изменение размера канала на большее, чем единичное, не повлияет на текущее выставленное поведение, то есть ожидание, пока хотя бы одна из двух подпрограмм go завершит выполнение операции Copy.

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