2016-11-18 4 views
3

gzip圧縮jsonパケットをネットワーク接続から読み取るプログラムがあります。送信者は、gzipパケットを送信した後に接続を閉じません。 go1.6.3では、gzipエンドシーケンスが受信された後にgzipパケットがデコードされますが、go1.7.3では、io.EOFが存在しないため、リーダーブロックが完全に機能します。golip 1.7.3のgzipリーダーの動作変更(1.6.3と比較)

    :私は2つの質問を持っている

    この状況を踏まえ
    package main 
    
    import (
        "fmt" 
        "encoding/json" 
        "compress/gzip" 
        "io" 
        "runtime" 
    ) 
    
    type TestJSON struct { 
        TestString string `json:"test"` 
    } 
    
    func main() { 
        fmt.Printf("Version: %s\n", runtime.Version()) 
        pipeReader, pipeWriter := io.Pipe(); 
    
        go writeTo(pipeWriter); 
        readFrom(pipeReader); 
    } 
    
    func writeTo(pipeWriter *io.PipeWriter){ 
        // marshall and compress 
        testJSON := TestJSON{TestString: "test",} 
    
        jsonString, err := json.Marshal(testJSON) 
        if err != nil { 
         fmt.Printf("Marshalling Error: %s\n", err) 
         return 
        } 
    
        gzipOut := gzip.NewWriter(pipeWriter) 
        _, err = gzipOut.Write(jsonString) 
        if err != nil { 
         fmt.Printf("Error Writing: %s\n", err) 
         return 
        } 
        gzipOut.Close() 
        //pipeWriter.Close() 
    } 
    
    func readFrom(pipeReader *io.PipeReader){ 
        // decompress and unmarshall 
        gzipIn, err := gzip.NewReader(pipeReader) 
        if err != nil { 
         fmt.Printf("Error creating reader: %s\n", err) 
         return 
        } 
        defer gzipIn.Close() 
    
        jsonDecoder := json.NewDecoder(gzipIn) 
        msg := new(TestJSON) 
        err = jsonDecoder.Decode(msg) 
        if err != nil { 
         fmt.Printf("Error decoding: %s\n", err) 
         return 
        } 
        fmt.Printf("Recived: %v\n", msg) 
    } 
    

    :ここ

    は、パイプを使用してネットワーク接続をシミュレートしたサンプルは、(ライターがオープン接続をシミュレートするために開いたままということに注意してください)です
  1. 正しい動作はどれですか?
  2. go1.7.3が正しく動作する場合、開いているネットワーク接続で受信したgzipパケットをどのようにデコードできますか?

答えて

2

あなたが見ているのは正しい動作です。 gzip.Readerの古い動作は、io.EOF、最後に(0, io.EOF)を指定せずに最後の読み取りを返すことができるという副作用でした。 io.EOFが正常に待機するようになったので、次のgzipヘッダーまたはio.EOFの待機をブロックします。

さらに多くのファイルが必要ではなく、io.EOFにかかわらずgzipトレイラーにファイルの最後を示す場合は、Reader.Multistream(false)と設定する必要があります。

func readFrom(pipeReader *io.PipeReader) { 
    // decompress and unmarshall 
    gzipIn, err := gzip.NewReader(pipeReader) 
    if err != nil { 
     fmt.Printf("Error creating reader: %s\n", err) 
     return 
    } 
    gzipIn.Multistream(false) 

https://play.golang.org/p/BdaulxMza0

あなたの例では、そのほかで動作します

関連する問題