Потоки канала Голанг

Я относительно новичок в Golang и не совсем понимаю потоки. У меня есть функция (функция автоматического выключателя), которая выполняет вызовы Rest. У меня он работает, но он только передает обратно "responseBody". На самом деле я хотел бы вернуть весь запрос потока назад как для тела, так и для заголовка вместе.

Когда я пытаюсь использовать аналогичный подход к «заголовку», я получаю сообщение об ошибке, что заголовок не является потоковым.

Есть ли хороший/лучший способ сделать это? Спасибо. Ниже моя функция.

func CallWithRetries(req *http.Request, output chan []byte) error {
    r := retrier.New(retrier.ConstantBackoff(RETRIES, 100 * time.Millisecond), nil)
    attempt := 0
    err := r.Run(func() error {
        attempt++
        resp, err := Client.Do(req)
        if err == nil && resp.StatusCode < 299 {
            responseBody, err := ioutil.ReadAll(resp.Body)
            if err == nil {
                output <- responseBody
                return err
            }
            return err
        } else if err == nil {
            customLogger.LogDebug("Status code was: " , transactionId)
            err = fmt.Errorf("Status was %v", resp.StatusCode)
        }
        return err
    })
    return err
}

person mornindew    schedule 27.08.2018    source источник
comment
Поскольку ваш канал ожидает значения типа []byte, а заголовки HTTP имеют тип [][]string. Найдите способ сериализовать заголовки в []byte.   -  person icza    schedule 27.08.2018
comment
output — это chan []byte в вашем примере, а заголовки ответа не хранятся в []byte, поэтому вы не можете отправить его через свой канал. Просто преобразуйте их в формат []byte (например, упорядочив их в объект JSON), и вы сможете их отправлять.   -  person Ullaakut    schedule 27.08.2018
comment
Просто для справки в ваших будущих поисках, это обычно не называют потоковой передачей. Потоковая передача обычно относится к обработке (чтению или записи) потока данных, который в Go обычно представлен как io.Reader/io.Writer. Использование каналов — это просто стандартный параллелизм Go.   -  person Adrian    schedule 27.08.2018


Ответы (1)


Вы ищете функцию https://golang.org/pkg/net/http/httputil/#DumpResponse.

Код может быть изменен на что-то похожее на

func CallWithRetries(req *http.Request, output chan []byte) error {
    r := retrier.New(retrier.ConstantBackoff(RETRIES, 100*time.Millisecond), nil)
    attempt := 0
    err := r.Run(func() error {
        attempt++
        resp, err := Client.Do(req)
        if err == nil && resp.StatusCode < 299 {
            dump, err := httputil.DumpResponse(resp, true)
            if err == nil {
                output <- dump
                return err
            }
            return err
        } else if err == nil {
            customLogger.LogDebug("Status code was: ", transactionId)
            err = fmt.Errorf("Status was %v", resp.StatusCode)
        }
        return err
    })
    return err
}

Боковые примечания,

  • возможно, вы захотите закрыть тело ответа, как указано в документации https://golang.org/pkg/net/http/#Client.Get

  • Похоже, что переменная err затенена, это следует изменить, чтобы избежать каких-либо неожиданностей.

Эта версия кода пытается вернуть ошибки раньше и закрыть тело ответа. Он не был протестирован, только написан на лету, чтобы использовать его с осторожностью.

func CallWithRetries(req *http.Request, output chan []byte) error {
    r := retrier.New(retrier.ConstantBackoff(RETRIES, 100*time.Millisecond), nil)
    attempt := 0
    return r.Run(func() error {
        attempt++
        var resp *http.Response
        {
            r, err := Client.Do(req)
            if err != nil {
                return err
            }
            defer r.Body.Close()
            if resp.StatusCode > 299 {
                customLogger.LogDebug("Status code was: ", transactionId)
                return fmt.Errorf("Status was %v", resp.StatusCode)
            }
            resp = r
        }
        var out []byte
        {
            x, err := httputil.DumpResponse(resp, true)
            if err != nil {
                return err
            }
            out = x
        }
        output <- out
        return nil
    })
}
person mh-cbon    schedule 27.08.2018
comment
Спасибо @mh-cbon - ваш ответ был очень полезным и понятным. Это именно то, что мне нужно. Я очень ценю это (и дополнительную помощь, которую вы оказали). - person mornindew; 28.08.2018