无法覆盖文件内容

Trouble overwriting file content

我无法用零覆盖文件内容。问题是原始文件的最后一个字节仍然存在,即使我超过了它的大小 100 个字节。有人知道我错过了什么吗?

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    f, err := os.Create("received.dat")
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    defer f.Close()

    _, err = io.Copy(f, r.Body)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    // Retrieve filesize
    size, _ := f.Seek(0, 1)
    zeroFilled := make([]byte, size + 100)
    n, err := f.WriteAt(zeroFilled, 0)
    if err != nil {
        return
    }

    fmt.Printf("Size: %d\n", size) // prints 13
    fmt.Printf("Bytes written: %d\n", n) // prints 113
}

发生此问题的原因可能是数据写入了 http 处理程序内的同一文件(共享资源),并且处理程序本身可能并发执行。您需要在数据序列化(覆盖过程)期间锁定对文件的访问。快速解决方案将是:

import (
   "sync"
   //... other packages
)

var muFile sync.Mutex

func (h PostKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    muFile.Lock()
    defer muFile.Unlock()

    f, err := os.Create("received.dat")
    //other statements
    //...
}

如果您的服务器负载较低,上述解决方案就可以了。但是如果你的服务器需要并发处理很多请求,你需要使用不同的方法(虽然规则是一样的,锁定对任何共享资源的访问)。

我正在写入文件并试图在相同的上下文中覆盖它,因此第一次写入操作的部分内容仍在内存中,尚未写入磁盘。通过在复制正文内容后使用 f.Sync() 刷新所有内容,我能够解决问题。