Ваш код работает "как положено", и то, что вы написали в Go, не эквивалентно коду, показанному в Node.js. Go кодовые блоки на ioutil.ReadAll(resp.Body)
, поскольку соединение остается открытым сервером CouchDB. Как только сервер закроет соединение, ваш клиентский код распечатает result
, поскольку ioutil.ReadAll()
сможет прочитать все данные до EOF.
Из Документация CouchDB о непрерывной подаче:
Непрерывный канал остается открытым и подключенным к базе данных до тех пор, пока не будет явно закрыт, и изменения будут отправлены клиенту по мере их появления, то есть почти в реальном времени. Как и в случае с типом ленты longpoll, вы можете установить интервалы времени ожидания и пульса, чтобы соединение оставалось открытым для новых изменений и обновлений.
Вы можете попробовать поэкспериментировать и добавить &timeout=1
к URL, который заставит CouchDB закрыть соединение через 1 с. Ваш код Go затем должен напечатать весь ответ. Код
Node.js работает по-другому, обработчик события data
вызывается каждый раз, когда сервер отправляет некоторые данные. Если вы хотите добиться того же и обрабатывать частичные обновления по мере их поступления (до закрытия соединения), вы не можете использовать ioutil.ReadAll () , поскольку он ожидает EOF (и, следовательно, блокирует в вашем случае), но что-то вроде resp.Body.Read()
для обработки частичных буферов. Вот очень упрощенный фрагмент кода, который демонстрирует это и должен дать вам основную c идею:
package main
import (
"fmt"
"net/http"
"net/url"
"strings"
)
func main() {
client := &http.Client{}
data := url.Values{}
req, err := http.NewRequest("GET", "http://localhost:3030/downloads/_changes?feed=continuous&include_docs=true", strings.NewReader(data.Encode()))
req.Header.Set("Connection", "keep-alive")
resp, err := client.Do(req)
defer resp.Body.Close()
fmt.Println(resp.Status)
if err != nil {
fmt.Println(err)
}
buf := make([]byte, 1024)
for {
l, err := resp.Body.Read(buf)
if l == 0 && err != nil {
break // this is super simplified
}
// here you can send off data to e.g. channel or start
// handler goroutine...
fmt.Printf("%s", buf[:l])
}
fmt.Println()
}
В реальном приложении вы, вероятно, захотите убедиться, что ваш buf
содержит нечто, похожее на действительное сообщение, а затем передайте его в канал или обработчик для дальнейшей обработки.