>백엔드 개발 >Golang >고루틴을 사용하여 Zip을 빌드하면 슬라이스가 범위를 벗어났고 용량은 4096입니다.

고루틴을 사용하여 Zip을 빌드하면 슬라이스가 범위를 벗어났고 용량은 4096입니다.

王林
王林앞으로
2024-02-09 16:27:081101검색

使用 goroutine 构建 Zip,切片超出范围,容量为 4096

php 편집자 Xiaoxin이 goroutine을 사용하여 Zip을 빌드하는 방법에 대한 기사를 가져왔습니다. 이 기사에서는 프로그램의 효율성을 높이기 위해 고루틴을 사용하여 Zip 작업을 동시에 수행하는 방법을 알아봅니다. 또한 범위를 벗어난 슬라이스 문제에 대해 논의하고 이 문제를 해결하기 위해 4096 용량의 슬라이스를 사용하는 방법을 보여줍니다. 초보자이든 숙련된 개발자이든 이 글은 고루틴 및 슬라이싱과 관련된 지식을 더 잘 이해하고 적용하는 데 도움이 될 것입니다. 함께 탐험해 보세요!

질문 내용

아카이브해야 하는 각 파일을 처리하는 고루틴을 추가하여 zip을 빌드하는 기능을 개선하려고 합니다. 하지만 패닉상태로 끝났다 panic:运行时错误:切片超出范围[4126:4096]

대상 디렉터리에는 190개의 파일(500개월)이 포함되어 있습니다. 나는 정말로 무엇이 잘못되었는지 이해하지 못한다. 도움을 주셔서 미리 감사드립니다

특징:

으아악

여기서 오류가 발생했습니다:

으아악

스택 추적:

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                                                                     
}

Solution

zip.Writer 동시 사용에는 안전하지 않습니다. 여러 고루틴을 시작하면 각 고루틴은 zip 항목(파일)을 생성하고 씁니다.

Writer.Create() 기록:

Create는 제공된 이름을 사용하여 zip 파일에 파일을 추가합니다. 파일 내용을 써야 하는 Writer를 반환합니다.

[...] 다음번 Create, CreateHeader 또는 Close 호출 전에 파일 내용을 io.Writer에 작성해야 합니다.

동시에 zip을 생성할 수 없습니다. io.Writers 写入相同的底层文件(或一般情况下相同的 io.Writer) 각 zip 항목에 대해 애플리케이션이 당황하거나 충돌하지 않더라도 결과 zip 아카이브가 유효하지 않을 수 있습니다.

위 내용은 고루틴을 사용하여 Zip을 빌드하면 슬라이스가 범위를 벗어났고 용량은 4096입니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 stackoverflow.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제