Одновременно отправлять байты из потока в два места назначения - PullRequest
2 голосов
/ 15 июня 2019

Каков наилучший способ широковещательной передачи значений из потока в две сети одновременно? Вот упрощенный код:

func main() {
    resp, _ := http.Get("http://origin.com/image.jpeg")

    var buf bytes.Buffer
    // tee, when read, writes to &buf
    respBodyTee := io.TeeReader(resp.Body, &buf)

    sendToClient(respBodyTee)
    uploadeToServer(&buf)
}

Поток не может быть прочитан дважды, поэтому TeeReader используется для заполнения &buf тем, что читается из respo.Body.

Однако функции (sendToClient и uploadToServer) будут работать синхронно, в то время как я хотел бы, чтобы они выполняли свою работу одновременно.

Решение, которое я имею в виду, состоит в том, чтобы передать канал на sendToClient, который заполнит канал байтами, уже отправленными клиенту. Позже прочитайте uploadToServer с того же канала. Что-то вроде этого:

func main() {
    resp, _ := http.Get("http://origin.com/image.jpeg")

    ch := make(chan byte)
    go sendToClient(respBodyTee, ch) // pass 'ch' for writing and run in a goroutine
    uploadeToServer(ch) // will read from 'ch' (synchronous)
}

Я новичок в Go и не уверен, что вышеприведенное является верным направлением.

1 Ответ

1 голос
/ 16 июня 2019

в вашем сценарии лучше иметь 2 независимых байтовых потока для 2 сетевых вызовов.Если они полагаются на один исходный поток, когда sendToClient stalls uploadeToServer зависнет.Канал не решит проблему, описанную выше, но введя издержки блокировки.

Вы можете попробовать io.MultiWriter, чтобы сделать 2 независимых потока байтов

var buf1, buf2 bytes.Buffer
mw := io.MultiWriter(&buf1, &buf2)

if _, err := io.Copy(mw, r.Body); err != nil {
    ...
}
go sendToClient(buf1)
go uploadeToServer(buf2)
...
...