2 回答
TA贡献1847条经验 获得超11个赞
首先,我不明白为什么你首先需要旗帜。根据我的理解,您可以省略.os.O_APPENDos.O_APPEND
现在,让我们来看看为什么会发生这种情况的实际问题:
文档 (参考: https://man7.org/linux/man-pages/man2/open.2.html):O_APPEND
O_APPEND
The file is opened in append mode. Before each write(2),
the file offset is positioned at the end of the file, as
if with lseek(2). The modification of the file offset and
the write operation are performed as a single atomic step.
因此,对于每个对文件的调用,偏移量都位于文件的末尾。write
但据说使用的是方法,即(*s3Manager.Download).DownloadWriteAt
文档 :WriteAt
$ go doc os WriteAt
package os // import "os"
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
WriteAt writes len(b) bytes to the File starting at byte offset off. It
returns the number of bytes written and an error, if any. WriteAt returns a
non-nil error when n != len(b).
If file was opened with the O_APPEND flag, WriteAt returns an error.
请注意最后一行,如果文件是用标志打开的,它将导致错误,它甚至是正确的,因为 WriteAt 的第二个参数是偏移量,但混合的行为和偏移量搜索可能会产生问题,导致意外的结果,并且它出错了。O_APPENDO_APPENDWriteAt
TA贡献1828条经验 获得超4个赞
考虑 s3 管理器的定义。下载器:
func (d Downloader) Download(w io.WriterAt, input *s3.GetObjectInput, options ...func(*Downloader)) (n int64, err error)
第一个参数是 ;此接口是:io.WriterAt
type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
这意味着该函数将调用您正在传递的方法中的方法。根据文件.写在的文档DownloadWriteAtFile
如果使用O_APPEND标志打开文件,则 WriteAt 将返回错误。
因此,这解释了为什么您会收到错误,但提出了一个问题“为什么使用和不接受(和调用)?答案可以在文档中找到:DownloadWriteAtio.WriterWrite
w io.作者可以通过操作系统来满足。用于执行多部分并发下载的文件,或使用 aws 在内存 [] 字节包装器中。写入缓冲区
因此,为了提高性能,可能会对文件的某些部分发出多个同时请求,然后在收到这些请求时将其写出(这意味着它可能不会按顺序写入数据)。这也解释了为什么多次调用函数时,使用相同的结果覆盖数据(当检索文件的每个块时,它会在输出文件中的适当位置将其写出;这将覆盖已经存在的任何数据)。DownloaderFileDownloader
文档中的上述引用也指出了一个可能的解决方案;使用 aws。WriteAtBuffer,下载完成后,将数据写入您的文件(然后可以使用 打开该文件) - 如下所示:O_APPEND
buf := aws.NewWriteAtBuffer([]byte{})
numBytes, err := downloader.Download(buf,
&s3.GetObjectInput{
Bucket: aws.String(Bucket),
Key: aws.String(fileToDownload),
})
if err != nil {
panic(err)
}
_, err = file.Write(buf.Bytes())
if err != nil {
panic(err)
}
另一种方法是下载到临时文件中,然后将其附加到输出文件中(如果文件很大,则可能需要执行此操作)。
- 2 回答
- 0 关注
- 63 浏览
添加回答
举报