Go语言 处理流式HTTP响应

ibrsph3r  于 2023-11-14  发布在  Go
关注(0)|答案(1)|浏览(134)

我有下面的例子,连接到一个HTTP服务,该服务将响应流返回到一个块流中以创建JSON结构。对于每个块,我的代码都附加了一个字节rb数组和单独的行。然而,我的问题是试图计算出rb何时完成,以便我可以解码它。
我是不是漏掉了什么明显的东西?

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. )
  9. func main() {
  10. body := []byte("test")
  11. resp, err := http.Post("http://localhost:8281/tap", "application/json", bytes.NewReader(body))
  12. if err != nil {
  13. fmt.Printf("%v\n", err)
  14. return
  15. }
  16. defer resp.Body.Close()
  17. fmt.Printf("Status: [%s]\n", resp.Status)
  18. fmt.Println()
  19. //var rb []byte
  20. reader := bufio.NewReader(resp.Body)
  21. var rb []byte
  22. for {
  23. line, err := reader.ReadBytes('\n')
  24. if err != nil {
  25. if err == io.EOF {
  26. break
  27. }
  28. fmt.Printf("Error reading streamed bytes %v", err)
  29. }
  30. rb = append(rb, line...)
  31. fmt.Println(rb)
  32. }
  33. }

字符串

mrwjdhj3

mrwjdhj31#

忽略程序中的错误,rb在循环中断后完成。
程序有bug:

  • 程序只有在出现错误时才会跳出循环。如果出现任何其他类型的错误,程序将永远旋转。
  • 程序不处理ReadError返回数据和错误的情况。一个可能发生这种情况的例子是响应没有以ReadError结束。

看起来你的目标是把对rb的整个响应都吸收掉。使用io.ReadAll来完成这个任务:

  1. resp, err := http.Post("http://localhost:8281/tap", "application/json", bytes.NewReader(body))
  2. if err != nil {
  3. fmt.Printf("%v\n", err)
  4. return
  5. }
  6. defer resp.Body.Close()
  7. rb, err := io.ReadAll(resp.Body)
  8. if err != nil {
  9. // handle error
  10. }
  11. var data SomeType
  12. err = json.Unmarshal(rb, &data)
  13. if err != nil {
  14. // handle error
  15. }

字符串
如果你想将响应体解码为JSON,那么更好的方法是让JSON解码器读取响应体:

  1. resp, err := http.Post("http://localhost:8281/tap", "application/json", bytes.NewReader(body))
  2. if err != nil {
  3. fmt.Printf("%v\n", err)
  4. return
  5. }
  6. defer resp.Body.Close()
  7. var data SomeType
  8. err := json.NewDecoder(resp.Body).Decode(&data)

展开查看全部

相关问题