I constantly write to one file some data everytime requests come in. I also want to parse this file and read from it sometimes. How can I do this reading if the file is cons
so you want Read & Write file without locking it,
Stateful Goroutines and channels are the solution:
one Stateful Goroutine manages the read and write requests.
working sample code:
package main
import "os"
import "fmt"
import "sync"
type Buffer struct {
buf []byte
off int64
}
var wg sync.WaitGroup
func main() {
wr := make(chan *Buffer)
rq := make(chan *Buffer)
rd := make(chan *Buffer)
wg.Add(1)
go manage("file.bin", wr, rq, rd)
wr <- &Buffer{buf: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, off: 0} //write
wr <- &Buffer{buf: []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, off: 10} //write
rq <- &Buffer{buf: make([]byte, 20), off: 0} //request to read
b := <-rd //read
fmt.Println("read:", b)
//read: &{[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19] 0}
rq <- &Buffer{buf: nil, off: -1} // exit
wg.Wait()
fmt.Println("Bye") //Bye
}
func manage(filename string, wr, rq, rd chan *Buffer) {
f, e := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if e != nil {
panic(e.Error())
}
defer f.Close()
for {
select {
case b := <-wr:
f.WriteAt(b.buf, b.off)
default:
}
select {
case b := <-rq:
if b.off == -1 {
wg.Done()
return
}
n, _ := f.ReadAt(b.buf, b.off)
rd <- &Buffer{b.buf[1:n], b.off}
default:
}
}
}
You could make use of sync.RWMutex. Then:
RLock()
, read, then call RUnlock()
.Lock()
, write, then call Unlock()
.As long as you do that, you're ensuring that:
Here's a very little example:
package sample
import (
"sync"
)
var fileMutex = new(sync.RWMutex)
func readFile() {
fileMutex.RLock()
defer fileMutex.RUnlock()
// Read the file. Don't modify it.
}
func writeFile() {
fileMutex.Lock()
defer fileMutex.Unlock()
// Write to the file.
}