2 回答
TA贡献1799条经验 获得超9个赞
Method2 和 Method3 弄乱了文本,因为在读取器和写入器共享的缓冲区上存在竞争。
以下是上述程序可能的语句执行顺序:
R: bytes_len, err = f.Read(buf)
R: ch<-buf[:bytes_len]
W: bytes, ok := <-ch; ok
R: bytes_len, err = f.Read(buf) // this writes over buffer
W: f.Write(bytes) // writes data from second read
使用种族检测器运行您的程序。它将为您标记问题。
解决问题的一种方法是复制数据。例如,从读取的字节创建一个字符串并将该字符串发送到通道。
另一种选择是将 goroutine 与io.Pipe连接。一个 goroutine 从源读取并写入管道。另一个 goroutine 从管道读取并写入目标。管道负责同步问题。
TA贡献1773条经验 获得超3个赞
为了使用您在注释中作为Method2and放置的 for 循环获取代码片段Method3,您将需要使用缓冲通道。
文本在目标文件中混乱的原因是循环 infunc main没有机制与在WriteFile.
另一方面,发送到缓冲通道,仅在缓冲区已满时阻塞。当缓冲区为空时接收块。因此,通过初始化缓冲区长度为 1 的通道,您可以使用Method1和/或Method2. 剩下的就是记住在完成后关闭通道。
func main() {
f, _ := os.OpenFile("test.txt", os.O_RDONLY, 0600)
defer f.Close()
ch := make(chan []byte, 1) // use second argument to make to give buffer length 1
buf := make([]byte, 10)
go WriteFile(ch)
for {
ch <- buf
byteLen, err := f.Read(buf)
if err != nil {
break
}
if byteLen < 10 {
ch <- buf[:byteLen]
break
}
}
close(ch) //close the channel when you done
}
func WriteFile(ch <-chan []byte) {
f, err := os.OpenFile("othertest.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)
defer f.Close()
if err != nil {
fmt.Println("* Error:", err)
return
}
//Method 3: use "for range"
for data := range ch {
f.Write(data)
}
}
- 2 回答
- 0 关注
- 159 浏览
添加回答
举报