byte[] channel usage

10.7k Views Asked by At

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

There are 1 best solutions below

2
On BEST ANSWER

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
}