php小編小新帶來了一篇關於使用goroutine建構Zip的技巧文章。在這篇文章中,我們將了解如何利用goroutine並發執行Zip操作,以提高程式的效率。此外,我們還將討論切片超出範圍的問題,並介紹如何使用容量為4096的切片來解決這個問題。無論你是初學者還是有經驗的開發者,本文都將幫助你更好地理解和應用與goroutine和切片相關的知識。讓我們一起來探索吧!
我正在嘗試透過新增 goroutine 來處理每個必須存檔的檔案來改進建立 zip 的函數。
但最終卻以恐慌告終
panic:運行時錯誤:切片超出範圍[4126:4096
]
目標目錄包含 190 個檔案(500 mo)。 我實在不懂出了什麼問題 先感謝您的幫助
功能:
func buildarchive() error { var files []string err := filepath.walk("/tmp/dir-to-zip", func(filepath string, info os.fileinfo, err error) error { if info.isdir() { return nil } if err != nil { fmt.println(err) return err } files = append(files, filepath) return nil }) if err != nil { return err } bundle, err := os.create("/tmp/archive.zip") if err != nil { return err } bundlewriter := zip.newwriter(bundle) var wg sync.waitgroup wg.add(len(files)) for _, filepath := range files { go func(filepath string) { defer wg.done() relpath := strings.trimprefix(filepath, fmt.sprintf("%v/", filepath.dir("/tmp/dir-to-zip"))) bundlefile, err := bundlewriter.create(relpath) if err != nil { fmt.println(err) } fsfile, err := os.open(filepath) if err != nil { fmt.println(err) } _, err = io.copy(bundlefile, fsfile) if err != nil { fmt.println(err) } }(filepath) } wg.wait() err = bundlewriter.close() if err != nil { return err } return nil }
錯誤發生在這裡:
_, err = io.copy(bundlefile, fsfile) if err != nil { fmt.println(err) }
堆疊追蹤:
goroutine 48 [running]: bufio.(*Writer).Write(0xc00002a100, {0xc00041a400?, 0x3d?, 0xc00041a400?}) /usr/local/go/src/bufio/bufio.go:670 +0x1c8 archive/zip.(*countWriter).Write(0xc00000c138, {0xc00041a400?, 0x3d?, 0x4afa20?}) /usr/local/go/src/archive/zip/writer.go:601 +0x2e io.WriteString({0x4e7538, 0xc00000c138}, {0xc0000212c9, 0x3d}) /usr/local/go/src/io/io.go:314 +0x91 archive/zip.writeHeader({0x4e7538, 0xc00000c138}, 0xc000220090) /usr/local/go/src/archive/zip/writer.go:422 +0x5ec archive/zip.(*Writer).CreateHeader(0xc0000760a0, 0xc00021e1b0) /usr/local/go/src/archive/zip/writer.go:378 +0x797 archive/zip.(*Writer).Create(0x4e7698?, {0xc0000212c9, 0x3d}) /usr/local/go/src/archive/zip/writer.go:223 +0x6c main.BuildArchive.func2({0xc0000212c0, 0x46}) /home/simba/go/src/foobar/main.go:79 +0x1c5 created by main.BuildArchive /home/simba/go/src/foobar/main.go:73 +0x5aa panic: runtime error: slice bounds out of range [:4126] with capacity 4096 goroutine 6 [running]: bufio.(*Writer).Flush(0xc00002a100) /usr/local/go/src/bufio/bufio.go:634 +0x171 bufio.(*Writer).Write(0xc00002a100, {0xc0001b4200?, 0xc000199b20?, 0xc000199b20?}) /usr/local/go/src/bufio/bufio.go:672 +0xd8 archive/zip.(*countWriter).Write(0xc00000c138, {0xc0001b4200?, 0x0?, 0xc000199b40?}) /usr/local/go/src/archive/zip/writer.go:601 +0x2e archive/zip.(*countWriter).Write(0xc000220018, {0xc0001b4200?, 0xc0001b02c0?, 0xc0001b02f0?}) /usr/local/go/src/archive/zip/writer.go:601 +0x2e compress/flate.(*huffmanBitWriter).write(...) /usr/local/go/src/compress/flate/huffman_bit_writer.go:136 compress/flate.(*huffmanBitWriter).writeCode(0xc0001b41e0?, {0x6000?, 0x22?}) /usr/local/go/src/compress/flate/huffman_bit_writer.go:347 +0xe5 compress/flate.(*huffmanBitWriter).writeTokens(0xc0001b41e0, {0xc002558000, 0x4001, 0x403f800000403f?}, {0xc0001aa900, 0x11e, 0x108129000000000f?}, {0xc0001ac100, 0x1e, 0x1e}) /usr/local/go/src/compress/flate/huffman_bit_writer.go:583 +0xb9 compress/flate.(*huffmanBitWriter).writeBlock(0xc0001b41e0, {0xc002558000?, 0x20?, 0xd79?}, 0x0, {0x0, 0x0, 0x0}) /usr/local/go/src/compress/flate/huffman_bit_writer.go:495 +0x490 compress/flate.(*compressor).writeBlock(0xc0005a2000, {0xc002558000?, 0xc000032f00?, 0xc000199d28?}, 0x47739b?) /usr/local/go/src/compress/flate/deflate.go:170 +0x9c compress/flate.(*compressor).deflate(0xc0005a2000) /usr/local/go/src/compress/flate/deflate.go:509 +0x59b compress/flate.(*compressor).write(0xc0005a2000, {0xc00256a000?, 0x8000, 0xf311b6fd?}) /usr/local/go/src/compress/flate/deflate.go:554 +0x82 compress/flate.(*Writer).Write(...) /usr/local/go/src/compress/flate/deflate.go:712 archive/zip.(*pooledFlateWriter).Write(0xc00020c040?, {0xc00256a000?, 0x8000?, 0x4af140?}) /usr/local/go/src/archive/zip/register.go:51 +0xc5 archive/zip.(*countWriter).Write(...) /usr/local/go/src/archive/zip/writer.go:601 archive/zip.(*fileWriter).Write(0xc000222000, {0xc00256a000, 0x8000, 0x8000}) /usr/local/go/src/archive/zip/writer.go:533 +0x97 io.copyBuffer({0x4e7558, 0xc000222000}, {0x4e7678, 0xc0001f8008}, {0x0, 0x0, 0x0}) /usr/local/go/src/io/io.go:428 +0x204 io.Copy(...) /usr/local/go/src/io/io.go:385 main.BuildArchive.func2({0xc00001c0c0, 0x35}) /home/simba/go/src/foobar/main.go:89 +0x385 created by main.BuildArchive /home/simba/go/src/foobar/main.go:73 +0x5aa exit status 2
zip.Writer
並發使用不安全。您啟動多個 goroutine,每個 goroutine 建立並寫入 zip 條目(檔案)。
Writer.Create()
記錄:
建立使用提供的名稱將檔案加入 zip 檔案。它傳回一個 Writer,文件內容應寫入其中。
[...] 在下次呼叫 Create、CreateHeader 或 Close 之前,必須將檔案內容寫入 io.Writer。
您不能同時建立 zip。每個zip 條目的io.Writer
s 寫入相同的底層檔案(或一般情況下相同的io.Writer
),即使您的應用程式沒有出現恐慌或崩潰,產生的zip 檔案也可能無效。
以上是使用 goroutine 建構 Zip,切片超出範圍,容量為 4096的詳細內容。更多資訊請關注PHP中文網其他相關文章!