在Go 中使用net.Conn.Read 讀取可變長度資料
在Go 中使用網路應用程式時,您經常會遇到以下情況:透過連接接收的資料的長度是可變的。標準函式庫的net.Conn提供了一個名為Read的方法,它用接收到的資料填入位元組數組。然而,如果您事先不知道內容的確切長度,這種方法可能會出現問題,並可能導致讀取太多或不足的資料。
要解決這個挑戰,一個方法是利用 bufio包裹。然而,更有效的解決方案是採用不斷增長的緩衝區並讀取數據,直到遇到文件結尾(EOF):
package main import ( "fmt" "io" "net" ) func main() { // Establish a connection with a remote host. conn, err := net.Dial("tcp", "google.com:80") if err != nil { fmt.Println("dial error:", err) return } defer conn.Close() // Write a request to the connection. fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") // Create a buffer to store the received data. buf := make([]byte, 0, 4096) // Read from the connection in a loop until EOF. for { // Read into a temporary buffer to avoid overwriting existing data in `buf`. tmp := make([]byte, 256) n, err := conn.Read(tmp) if err != nil { if err != io.EOF { fmt.Println("read error:", err) } break } // Append the new data to the buffer. buf = append(buf, tmp[:n]...) } fmt.Println("total size:", len(buf)) }
此解決方案分配相當大的初始緩衝區,並逐漸將其擴展為更多收到資料。它繼續讀取直到到達 EOF,確保緩衝區包含完整的回應。此外,它還追蹤接收到的資料的總大小。
或者,您可以將bytes.Buffer 類型與io.Copy 結合使用來實現類似的結果:
package main import ( "bytes" "fmt" "io" "net" ) func main() { // Establish a connection with a remote host. conn, err := net.Dial("tcp", "google.com:80") if err != nil { fmt.Println("dial error:", err) return } defer conn.Close() // Write a request to the connection. fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") // Create a buffer to store the received data. var buf bytes.Buffer // Copy the data from the connection into the buffer. io.Copy(&buf, conn) fmt.Println("total size:", buf.Len()) }
這種方法使用一個可以根據需要自動擴展的緩衝區,並提供更乾淨、更簡潔的解決方案。
以上是如何在 Go 中從網路連線讀取可變長度資料?的詳細內容。更多資訊請關注PHP中文網其他相關文章!