亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang 和不工作的函數 bytes.Contains()

Golang 和不工作的函數 bytes.Contains()

Go
鳳凰求蠱 2021-11-08 17:01:44
我有函數的奇怪問題bytes.Contains(b, subslice []byte) bool。它沒有在函數中接收到的字節數組中找到字符(c *IPConn) Read(b []byte) (int, error)。應用程序是一個簡單的服務器。所以我有字節數組,它是通過服務器接收到的變量bufbuf := make([]byte, 1024)Len, err := c.conn.Read(buf)// below received content in buf//{"abc":[{"b":5,"bca":14,"xyz":0}]}{"abc":[{"b":7,"hjk":14,"qwe":0}]}現在我想使用下面的函數在數組buf 中查找}{字符if bytes.Contains(buf, []byte(`}{`) != false {    fmt.Printf("I got you")}但是函數總是返回false。為什么 ?我在我的程序中做了一些實驗,如下所示:worker := []byte('{"abc":[{"b":5,"bca":14,"xyz":0}]}{"abc":[{"b":7,"hjk":14,"qwe":0}]}')// try find }{if bytes.Contains(worker, []byte(`}{`) != false {    fmt.Printf("I got you")}是正確的 !?。∥也幻靼走@一點......因為它允許通過服務器接收的數據之間的內容必須不同,并且數據形式通常是程序中的附件。
查看完整描述

2 回答

?
萬千封印

TA貢獻1891條經驗 獲得超3個贊

你真的檢查err和完成Lenc.conn.Read(buf)嗎?

您程序中的主要缺陷(如所示)是您buf用于搜索數據,而套接字上的讀取操作在接收到 1 到 1024 之間的任意數量的字節后可以自由返回成功,并在接收后返回錯誤0 到 1024 之間的任意字節數。

所以,你必須做兩件事:

  • 檢查錯誤;

  • 要在讀取操作結束后訪問緩沖區開頭的實際可用數據,您必須使用數據的實際長度Len.

要執行后者,您通常會構造一個新切片:

data := buf[:Len]

然后使用data變量:

if bytes.Contains(data, []byte("}{")) {

   ...

}

如果您不這樣做,您可能很容易訪問緩沖區中的陳舊數據 — 即,上次調用c.conn.Read(buf).

如果您再考慮一下這種情況,您會發現沒有什么可以保證Read()您的套接字上的下一次調用會將}{序列帶入緩沖區,并且您必須準備好累積數據:也就是說,

  1. 每次調用Read()都應將其Len字節添加到緩沖區中的字節數以供您的代碼考慮。

    這意味著如果第 N 個讀取操作未能提供您要查找的數據,則第 (N+1) 個操作必須將其字節放在前一個讀取操作的最后一個字節之后;在 Go 中,這通常意味著為下一個讀取操作構造另一個切片。

  2. 您應該使用當前累積的總字節數來搜索“}{”。

請考慮從本書開始,以掌握網絡編程的基礎知識(與 Go 相關的細節)。


如您所見,正確處理此任務看起來很復雜。那么為什么不讓 Go 自己做緩沖呢?

你可以這樣重申你的算法:

  1. 讀取輸入數據直到}找到一個字符。積累這些數據。

  2. 一旦}被發現,讀取下一個字符,如果是{,我們已經找到了點,我們感興趣的問題。

    否則返回步驟(1)。

這是可行的使用bytes.Buffer及其方法:

  • ReadBytes(delim byte)— 最多讀取一個}字節。

  • ReadByte()— 用于讀取單個字節以檢查是否{跟隨。

  • UnreadByte(c byte)— 用于將字節放回緩沖區,如果它不是{后續}.


現在讓我們從更一般的角度來看您的問題。您在示例中提供的數據在我看來就像一系列 JSON 對象。那么,您為什么要嘗試應用一些低技術方法來查找這些對象之間的邊界,而不是僅使用JSON 解碼器來立即解碼您的數據或至少正確地跳過流中的對象?


查看完整回答
反對 回復 2021-11-08
?
狐的傳說

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)

}

然后和測試數據對比看看有沒有差異,這是你說的唯一可能出錯的地方嗎?


查看完整回答
反對 回復 2021-11-08
  • 2 回答
  • 0 關注
  • 327 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號