为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
森栏 2022-10-31 16:51:37
我正在尝试在编写一个小程序的同时学习 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()
查看完整描述

1 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

以下循环挂起,因为chashes未关闭。


for hash := range chashes {

    fmt.Println(hash)

}

chashes在所有哈希器完成后通过关闭来修复。使用 sync.WaitGroup 等待哈希器完成。


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

    var wg sync.WaitGroup

    for filename := range cfiles {

        wg.Add(1)

        go func(filename string) {

            defer wg.Done()

            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()


            if !oError {

                hash := sha256.New()

                if _, err := io.Copy(hash, file); err != nil {

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

                    log.Println(errorMsg)

                    checksum = errorMsg

                }

                if len(checksum) == 0 {

                    checksum = hex.EncodeToString(hash.Sum(nil))

                }

            }

            chashes <- filename + "||" + checksum

        }(filename)

    } //for files


    // Wait for the hashers to complete.

    wg.Wait()


    // Close the channel to cause main() to break

    // out of for range on chashes.

    close(chashes)

}

defer close(chashes)从中删除run()。

在 Go 操场上运行一个示例



查看完整回答
反对 回复 2022-10-31
  • 1 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信