我使用以下代码来检索由跟踪/事件数据块组成的 HTTP 流。该代码将每一行打印到 stdout,最终成为有效的 JSON 结构。但是,我正在尝试将 JSON 输出转换为单个完整字符串,我可以将其解组为数据结构。
由于它是一个流,我使用 for 循环来连续捕获流数据。rb然而,在 for 循环的每次迭代期间附加的我的字节数组rb = append(rb, line...)似乎包含相同数据的多个/重复副本。
rb
rb = append(rb, line...)
是否有明显的模式来捕获这些多行事件并将它们缝合在一起作为一个实体?
package main import ( "bufio" "bytes" "fmt" "io" "net/http" ) func main() { c := `yaml data` body := []byte(c) resp, err := http.Post("http://localhost:8281/feed", "application/json", bytes.NewReader(body)) if err != nil { fmt.Printf("%v\n", err) return } defer resp.Body.Close() fmt.Printf("Status: [%s]\n", resp.Status) fmt.Println() //var rb []byte reader := bufio.NewReader(resp.Body) var rb []byte for { line, err := reader.ReadBytes('\n') if err != nil { if err == io.EOF { break } fmt.Printf("Error reading streamed bytes %v", err) } rb = append(rb, line...) fmt.Printf("---------need data from here ! ------") fmt.Printf("%s", string(rb)) } }
在你的代码中,问题是每次迭代循环时,你都会将line附加到rb,而这导致了rb的内容重复。你可以简化代码,只附加新行,而不是整个rb,然后在循环外部构建完整的JSON字符串。
line
以下是一个修复的示例:
package main import ( "bufio" "fmt" "io" "net/http" "strings" ) func main() { c := `yaml data` body := []byte(c) resp, err := http.Post("http://localhost:8281/feed", "application/json", strings.NewReader(string(body))) if err != nil { fmt.Printf("%v\n", err) return } defer resp.Body.Close() fmt.Printf("Status: [%s]\n", resp.Status) fmt.Println() reader := bufio.NewReader(resp.Body) var rb string // 使用字符串而不是字节数组 for { line, err := reader.ReadString('\n') if err != nil { if err == io.EOF { break } fmt.Printf("Error reading streamed bytes %v", err) } rb += line // 附加新行 // 在这里判断是否已经完整获取了一个JSON对象 if strings.Contains(rb, "}") { // 解析和处理 rb 中的 JSON 数据 fmt.Printf("Complete JSON: %s", rb) // 重置 rb 以准备接收下一个 JSON 对象 rb = "" } } }
在上面的示例中,我们将每行添加到字符串rb,然后检查rb是否包含一个完整的JSON对象。如果是,就可以解析和处理该JSON对象,并在处理完成后重置rb以接收下一个JSON对象。这样,你可以逐步构建完整的JSON字符串并解析它们。请确保根据你的需求进行适当的JSON解析和处理。