我希望每当文件打开时,我的 go 例程都会从新文件中读取。为此,我使用互斥体来做到这一点。但输出似乎并没有达到预期。在 f1.txt 中我有
hello
,在 f2.txt 中我有 world
。我正在这两个文件之间切换。
type Root struct {
File *os.File
sync.RWMutex
}
func main() {
startWorker()
}
func startTask(root *Root) {
interval := 1 * time.Second
ticker := time.NewTicker(interval)
defer ticker.Stop()
i := 0
for {
go func(i int, root *Root) {
root.RLock()
defer root.RUnlock()
content, _ := io.ReadAll(root.File)
fmt.Printf("go routine %v is reading data %s\n", i, content)
}(i, root)
i++
<-ticker.C
}
}
func startWorker() {
interval := 4 * time.Second
ticker := time.NewTicker(interval)
defer ticker.Stop()
f1 := "concurrent/1/f1.txt"
f2 := "concurrent/2/f2.txt"
f := f1
file, _ := os.Open(f)
root := &Root{File: file}
go startTask(root)
for {
root.Lock()
if f == f2 {
f = f1
} else {
f = f2
}
root.File.Close()
file, _ := os.Open(f)
root.File = file
root.Unlock()
<-ticker.C
}
}
输出看起来如下
go routine 0 is reading data world
go routine 1 is reading data
go routine 2 is reading data
go routine 3 is reading data
go routine 4 is reading data hello
go routine 5 is reading data
go routine 6 is reading data
go routine 7 is reading data
go routine 8 is reading data world
go routine 9 is reading data
问题在于
io.ReadAll(root.File)
读取到文件末尾,而后续读取结果为空。通过在读取之前查找文件的开头来修复。
go func(i int, root *Root) {
root.RLock()
defer root.RUnlock()
root.File.Seek(0, os.SEEK_SET)
content, _ := io.ReadAll(root.File)
fmt.Printf("go routine %v is reading data %s\n", i, content)
}(i, root)