2 回答

TA貢獻1891條經驗 獲得超3個贊
你真的檢查err
和完成Len
后c.conn.Read(buf)
嗎?
您程序中的主要缺陷(如所示)是您buf
用于搜索數據,而套接字上的讀取操作在接收到 1 到 1024 之間的任意數量的字節后可以自由返回成功,并在接收后返回錯誤0 到 1024 之間的任意字節數。
所以,你必須做兩件事:
檢查錯誤;
要在讀取操作結束后訪問緩沖區開頭的實際可用數據,您必須使用數據的實際長度
Len
.
要執行后者,您通常會構造一個新切片:
data := buf[:Len]
然后使用data
變量:
if bytes.Contains(data, []byte("}{")) {
...
}
如果您不這樣做,您可能很容易訪問緩沖區中的陳舊數據 — 即,上次調用c.conn.Read(buf)
.
如果您再考慮一下這種情況,您會發現沒有什么可以保證Read()
您的套接字上的下一次調用會將}{
序列帶入緩沖區,并且您必須準備好累積數據:也就是說,
每次調用
Read()
都應將其Len
字節添加到緩沖區中的字節數以供您的代碼考慮。這意味著如果第 N 個讀取操作未能提供您要查找的數據,則第 (N+1) 個操作必須將其字節放在前一個讀取操作的最后一個字節之后;在 Go 中,這通常意味著為下一個讀取操作構造另一個切片。
您應該使用當前累積的總字節數來搜索“}{”。
請考慮從本書開始,以掌握網絡編程的基礎知識(與 Go 相關的細節)。
如您所見,正確處理此任務看起來很復雜。那么為什么不讓 Go 自己做緩沖呢?
你可以這樣重申你的算法:
讀取輸入數據直到
}
找到一個字符。積累這些數據。一旦
}
被發現,讀取下一個字符,如果是{
,我們已經找到了點,我們感興趣的問題。否則返回步驟(1)。
這是可行的使用bytes.Buffer
及其方法:
ReadBytes(delim byte)
— 最多讀取一個}
字節。ReadByte()
— 用于讀取單個字節以檢查是否{
跟隨。UnreadByte(c byte)
— 用于將字節放回緩沖區,如果它不是{
后續}
.
現在讓我們從更一般的角度來看您的問題。您在示例中提供的數據在我看來就像一系列 JSON 對象。那么,您為什么要嘗試應用一些低技術方法來查找這些對象之間的邊界,而不是僅使用JSON 解碼器來立即解碼您的數據或至少正確地跳過流中的對象?

TA貢獻1804條經驗 獲得超3個贊
您的代碼缺少一些括號等存在問題。這似乎有效:
package main
import (
"bytes"
"fmt"
)
const data = `{"abc":[{"b":5,"bca":14,"xyz":0}]}{"abc":[{"b":7,"hjk":14,"qwe":0}]}`
func main() {
buf := []byte(data)
fmt.Printf("buf = %s\n", string(buf))
if bytes.Contains(buf, []byte("}{")) {
fmt.Printf("I got you\n")
}
}
在您連接的應用程序中接收數據可能存在編碼問題,這是一個棘手的問題,我有時會使用打印接收數據的十六進制值來真正查看線路中出現的內容。
編輯 :
嘗試像這樣打印出接收到的數據:
for _, b := range buf {
fmt.Printf("%X ", b)
}
然后和測試數據對比看看有沒有差異,這是你說的唯一可能出錯的地方嗎?
- 2 回答
- 0 關注
- 327 瀏覽
添加回答
舉報