字节流通道使用

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

byte[] channel usage

问题

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

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被定义为:BodyChannel chan []byte

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

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看到了这一点。在这种情况下一切正常。
问题是当消息在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:

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

The BodyChannel is defined: BodyChannel chan []byte

I use this class as follows:

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

Listening part:

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

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

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

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方法的切片。如果你想在其他地方使用这些数据,你需要对其进行复制。

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
}
英文:

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

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

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:

确定