我想从一些ajax脚本向一个文件写入请求。问题出现在一秒钟内会有很多这样的问题,写入文件将比请求之间的中断花费更多的时间,并且同时会有两个请求。
我怎么解决这个问题?
我使用互斥量,比如:
var mu sync.Mutex
func writeToFile() {
mu.Lock()
defer mu.Unlock()
// write to file
}
但它使整个事情同步,我真的不知道当同时有两个请求时会发生什么。它仍然不会锁定文件本身。
呃,这样做的正确方法是什么?
答案 0 :(得分:4)
您只需要将文件写入“顺序”,这意味着不允许2个并发的goroutine写入文件。是的,如果您在writeToFile()
函数中使用锁定,那么提供ajax请求也可能(部分)顺序。
我建议您在应用程序启动时打开文件一次。并指定一个单独的goroutine,负责写入文件,没有其他goroutines应该这样做。
使用缓冲通道发送应写入文件的数据。这将使服务ajax请求无阻塞,并且仍然不会同时/并行地写入文件。
请注意,这样ajax请求甚至不必在数据实际写入文件时等待(响应时间更快)。这可能是也可能不是问题。例如,如果稍后写入失败,则您的ajax响应可能已经提交=>没有机会向客户发出失败信号。
示例如何操作:
var (
f *os.File
datach = make(chan []byte, 100) // Buffered channel
)
func init() {
// Open file for appending (create if doesn't exist)
var err error
f, err = os.OpenFile("data.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
panic(err)
}
// Start goroutine which writes to the file
go writeToFile()
}
func writeToFile() {
// Loop through any data that needs to be written:
for data := range datach {
if _, err := f.Write(data); err != nil {
// handle error!
}
}
// We get here if datach is closed: shutdown
f.Close()
}
func ajaxHandler(w http.ResponseWriter, r *http.Request) {
// Assmeble data that needs to be written (appended) to the file
data := []byte{1, 2, 3}
// And send it:
datach <- data
}
要正常退出应用程序,您应该关闭datach
频道:当它关闭时,writeToFile()
中的循环将终止,文件将被关闭(刷新任何缓存的数据,释放OS资源)。
如果您想在文件中写入文字,可以像这样声明data
频道:
var datach = make(chan string, 100) // Buffered channel
您可以使用File.WriteString()
将其写入文件:
if _, err := f.WriteString(data); err != nil {
// handle error!
}