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 關注
- 87 瀏覽
添加回答
舉報