字节流通道使用

huangapple go评论116阅读模式
英文:

byte[] channel usage

问题

我正在收到一个REST命令,并希望对其主体进行哈希函数计算。
为此,我使用io.TeeReader(request.Body, &writerToHash)读取主体,其中我传递了自己实现的实现了io.Writer接口的类:

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

BodyChannel被定义为:BodyChannel chan []byte

我按以下方式使用这个类:

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

监听部分:

  1. func (wth *WriterToHash) StartListen() {
  2. wth.OutChannel = make(chan []byte, 1000)
  3. go func(self *WriterToHash) {
  4. done := int64(0)
  5. h := sha1.New()
  6. for done < MessageSize {
  7. buff := <-self.BodyChannel
  8. done += int64(len(buff))
  9. DPrint(5, "AccamulateSha1 Done=: %v, buff=%v", done, buff) //PRINT 2
  10. actually_write, err := h.Write(buff)
  11. if err != nil || actually_write != len(buff) {
  12. log.Println("Error in sha write:" + err.Error())
  13. break
  14. }
  15. }
  16. bs := h.Sum(nil)
  17. self.OutChannel <- bs
  18. }(wth)
  19. }

我发送的消息大小为1000字节。在调试模式下,消息总是以相同的方式分割:1字节,999字节 - 我通过PRINT 1看到了这一点。在这种情况下一切正常。
问题是当消息在Write函数中分成多个部分时。在PRINT 1中我看到:

[第一个字节]:a

[接下来的约450字节]:b,c,d,...

[最后的约550字节]:w,x,y,...

但在PRINT 2中我看到不同的情况:

[第一个字节]:a

[约450字节,但从最后一部分开始]:w,x,y...

[最后的约550字节]:w,x,y...

我实际上两次获取了最后一部分,但大小不同。

英文:

I am getting a REST command, and want to calculate hash function on it's body.
To do so I read the body using io.TeeReader(request.Body, &amp;writerToHash) where I pass my own class that implements io.Writer:

  1. func (self *WriterToHash) Write(p []byte) (n int, err error) {
  2. n=len(p)
  3. fmt.println(&quot;WriterToHash len=%v, buff=%v&quot;, n, p) //PRINT 1
  4. self.BodyChannel &lt;- p
  5. return n, nil
  6. }

The BodyChannel is defined: BodyChannel chan []byte

I use this class as follows:

  1. writerToHash := sisutils.WriterToHash{
  2. BodyChannel:make(chan []byte, 1024)
  3. }
  4. writerToHash.StartListen()
  5. reqnew, _ := http.NewRequest(&quot;PUT&quot;, url, io.TeeReader(request.Body, &amp;writerToHash))

Listening part:

  1. func (wth *WriterToHash) StartListen() {
  2. wth.OutChannel = make(chan []byte, 1000)
  3. go func (self *WriterToHash) {
  4. done := int64(0)
  5. h := sha1.New()
  6. for done &lt; MessageSize{
  7. buff := &lt;- self.BodyChannel
  8. done += int64(len(buff))
  9. DPrint(5, &quot;AccamulateSha1 Done=: %v, buff=%v&quot;, done, buff) //PRINT 2
  10. actually_write, err := h.Write(buff)
  11. if err != nil || actually_write != len(buff) {
  12. log.Println(&quot;Error in sha write:&quot; + err.Error())
  13. break
  14. }
  15. }
  16. bs := h.Sum(nil)
  17. self.OutChannel &lt;- bs
  18. }(wth)
  19. }

I send messages of 1000 bytes. In debug mode the message is always split in the same way: 1 byte, 999 bytes - I see it using PRINT 1. In this case everythong works fine.
The problem is that when the message is split to more parts in the Write function. In this case I see in PRINT1:

[first byte] : a

[next ~450 bytes] : b,c,d,...

[last ~550 bytes] : w,x,y,...

but in PRINT 2 I see different picture:

[first byte] : a

[ ~450 bytes but starting where last part starts] : w,x,y...

[last ~550 bytes] : w,x,y,...

I actually get the last past twice but not in the same size.

答案1

得分: 6

io.Writer文档中:

> Write不能修改切片数据,即使是临时的。实现不能保留p。

你不能存储或重用传递给Write方法的切片。如果你想在其他地方使用这些数据,你需要对其进行复制。

  1. func (self *WriterToHash) Write(p []byte) (n int, err error) {
  2. b := make([]byte, len(p))
  3. copy(b, p)
  4. fmt.println("WriterToHash len=%d, buff=%v", len(p), b)
  5. self.BodyChannel <- b
  6. return len(p), nil
  7. }
英文:

From the io.Writer documentation:

> Write must not modify the slice data, even temporarily. Implementations must not retain p

You can't store or reuse the slice being passed to your Write method. If you want to use that data elsewhere, you need to make a copy of it

  1. func (self *WriterToHash) Write(p []byte) (n int, err error) {
  2. b := make([]byte, len(p))
  3. copy(b, p)
  4. fmt.println(&quot;WriterToHash len=%d, buff=%v&quot;, len(p), b)
  5. self.BodyChannel &lt;- b
  6. return len(p), nil
  7. }

huangapple
  • 本文由 发表于 2016年12月21日 03:46:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/41250130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定