英文:
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, &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("WriterToHash  len=%v, buff=%v", n, p)  //PRINT 1
    self.BodyChannel <- 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("PUT", url, io.TeeReader(request.Body, &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 < 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)
 }
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("WriterToHash  len=%d, buff=%v", len(p), b)
    self.BodyChannel <- b
    return len(p), nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论