Ety*_*Ety 2 channel go race-condition slice
我收到一个 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
}
Run Code Online (Sandbox Code Playgroud)
该BodyChannel定义:BodyChannel chan []byte
我使用这个类如下:
writerToHash := sisutils.WriterToHash{
BodyChannel:make(chan []byte, 1024)
}
writerToHash.StartListen()
reqnew, _ := http.NewRequest("PUT", url, io.TeeReader(request.Body, &writerToHash))
Run Code Online (Sandbox Code Playgroud)
听力部分:
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)
}
Run Code Online (Sandbox Code Playgroud)
我发送 1000 字节的消息。在调试模式下,消息总是以相同的方式拆分:1 个字节,999 个字节 - 我使用 PRINT 1 看到它。在这种情况下,everythong 工作正常。问题是当消息在 Write 函数中被拆分为更多部分时。在这种情况下,我在 PRINT1 中看到:
[第一个字节]:a
[下一个 ~450 字节] : b,c,d,...
[最后 ~550 字节]:w,x,y,...
但在 PRINT 2 中我看到不同的图片:
[第一个字节]:a
[~450 字节,但从最后一部分开始]:w,x,y...
[最后 ~550 字节]:w,x,y,...
我实际上得到了两次过去的过去,但大小不同。
写入不得修改切片数据,即使是临时修改。实现不能保留 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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6322 次 |
| 最近记录: |