频道挂起,可能没有在正确的地方关闭

我正在尝试在编写一个小程序的同时学习 Go。程序应该尽可能高效和快速地递归解析 PATH 并输出完整的文件名(包括路径)和文件的 sha256 文件哈希。


如果文件散列生成失败,我想保留错误并将其添加到字符串中(在散列位置)。


结果应在控制台上返回一个字符串,如:fileXYZ||hash


不幸的是,程序在某个时候挂起。我猜我的一些频道没有正确关闭并无限期地等待输入。我已经尝试了很长时间来解决这个问题,但没有成功。


有谁知道为什么输出挂起?很多人提前感谢,也欢迎对 Go 新手的任何输入/建议 ;-)。


(我编写了单独的函数,因为我想在解决此问题后添加其他功能。)


非常感谢!迪迪埃


这是代码:


import (

    "crypto/sha256"

    "encoding/hex"

    "flag"

    "fmt"

    "io"

    "log"

    "os"

    "path/filepath"

    "time"

)


func main() {

    pathParam := flag.String("path", ".", "Enter Filesystem Path to list folders")

    flag.Parse()

    start := time.Now()

    run(*pathParam)

    elapsed := time.Since(start)

    log.Printf("Time elapsed: %v", elapsed)

}


func run(path string) {

    chashes := make(chan string, 50)

    cfiles := make(chan string)


    go func() {

        readfs(path, cfiles)

        defer close(cfiles)

    }()

    go func() {

        generateHash(cfiles, chashes)

    }()

    defer close(chashes)

    for hash := range chashes {

        fmt.Println(hash)

    }

}


func readfs(path string, cfiles chan string) {

    files, err := os.ReadDir(path)

    if err != nil {

        log.Fatalln(err)

    }

    for _, file := range files {

        filename := filepath.Join(path, file.Name())

        if file.IsDir() {

            readfs(filename, cfiles)

            continue

        } else {

            cfiles <- filename

        }

    }

}


func generateHash(cfiles chan string, chashes chan string) {

    for filename := range cfiles {

        go func(filename string) {

            var checksum string

            var oError bool = false

            file, err := os.Open(filename)

            if err != nil {

                oError = true

                errorMsg := "ERROR: " + err.Error()

                log.Println(errorMsg)

                checksum = errorMsg

            }

            defer file.Close()




森栏
浏览 66回答 1
1回答

波斯汪

以下循环挂起,因为chashes未关闭。for hash := range chashes {&nbsp; &nbsp; fmt.Println(hash)}chashes在所有哈希器完成后通过关闭来修复。使用 sync.WaitGroup 等待哈希器完成。func generateHash(cfiles chan string, chashes chan string) {&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for filename := range cfiles {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(filename string) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var checksum string&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var oError bool = false&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; file, err := os.Open(filename)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oError = true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorMsg := "ERROR: " + err.Error()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(errorMsg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checksum = errorMsg&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer file.Close()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if !oError {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hash := sha256.New()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if _, err := io.Copy(hash, file); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorMsg := "ERROR: " + err.Error()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(errorMsg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checksum = errorMsg&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(checksum) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checksum = hex.EncodeToString(hash.Sum(nil))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chashes <- filename + "||" + checksum&nbsp; &nbsp; &nbsp; &nbsp; }(filename)&nbsp; &nbsp; } //for files&nbsp; &nbsp; // Wait for the hashers to complete.&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; // Close the channel to cause main() to break&nbsp; &nbsp; // out of for range on chashes.&nbsp; &nbsp; close(chashes)}defer close(chashes)从中删除run()。在 Go 操场上运行一个示例。
打开App,查看更多内容
随时随地看视频慕课网APP