2016-12-20 3 views
2

golangチャンネルで新しく説明できない奇妙な動作があります。 私はRESTコマンドを取得しており、その本体にハッシュ関数を計算したいと考えています。次のように私はこのクラスを使用BodyChannel chan []byteバイトゴランのチャンネル使用率

func (self *WriterToHash) Write(p []byte) (n int, err error) { 
    n=len(p) 
    fmt.println("WriterToHash len=%v, buff=%v", n, p) //PRINT 1 
    self.BodyChannel <- p 
    return n, nil 
} 

BodyChannelが定義されている: は私がio.Writerを実装して自分のクラスを渡すio.TeeReader(request.Body, &writerToHash)を使って身体を読んでこれを行うには

writerToHash := sisutils.WriterToHash{ 
     BodyChannel:make(chan []byte, 1024) 
    } 
    writerToHash.StartListen() 
    reqnew, _ := http.NewRequest("PUT", url, io.TeeReader(request.Body, &writerToHash)) 

リスニングパート:

func (wth *WriterToHash) StartListen() { 
    wth.OutChannel = make(chan []byte, 1000) 
    go func (self *WriterToHash) { 
     done := int64(0) 
     h := sha1.New() 
     for done < MessageSize{ 
      buff := <- self.BodyChannel 

      done += int64(len(buff)) 
      DPrint(5, "AccamulateSha1 Done=: %v, buff=%v", done, buff) //PRINT 2 

      actually_write, err := h.Write(buff) 
      if err != nil || actually_write != len(buff) { 
       log.Println("Error in sha write:" + err.Error()) 
       break 
      } 
     } 
     bs := h.Sum(nil) 
     self.OutChannel <- bs 
    }(wth) 
} 

私は1000バイトのメッセージを送信します。デバッグモードでは、メッセージは常に同じ方法で分割されます:1バイト、999バイト - 私はPRINT 1を使用してそれを見ます。この場合、everythongは正常に動作します。 問題は、メッセージが書き込み機能の複数の部分に分割されている場合です。この場合、私はPRINT1で参照してください。

[最初のバイト]:

[次〜450バイト]:B、C、D、...

[最後の〜550バイト]:ワット[最後の部分が始まる〜450のバイトが、出発]

[最初のバイト]、X、Yは、...

しかし

はPRINT 2に私は別の画像を参照して、W、X 、y ...

:w、x、y、...

私は実際に最後の過去を2回取得しますが、同じサイズではありません。

私はこれがなぜ起こっているのか分かりませんし、何か助けに感謝します。 io.Writer documentationから

答えて

3

書き込みは一時的であっても、スライスデータを変更してはなりません。実装ではpを保持しないでください

Writeメソッドに渡されるスライスを保存または再利用することはできません。そのデータを他の場所で使用したい場合は、そのデータをコピーする必要があります。

func (self *WriterToHash) Write(p []byte) (n int, err error) { 
    b := make([]byte, len(p)) 
    copy(b, p) 
    fmt.println("WriterToHash len=%d, buff=%v", len(p), b) 
    self.BodyChannel <- b 
    return len(p), nil 
} 
+0

ジムに感謝します。ところで、あなたはストリームが常に最初のバイト+残りに分割された理由を知っているかもしれませんか? – Ety

+0

@Ety:TeeReaderは読者から読まれたものを正確に書いています。したがって、1バイトが 'request.Body'から読み込まれた場合、1バイトは' writerToHash'に書き込まれます。小さな読み書き操作が問題になる場合(あなたの場合は問題ありません)、bufioを使用してより大きな操作にバッチ処理を行います。 – JimB

関連する問題