【问题标题】:main not exiting after reading from channel从频道读取后主不退出
【发布时间】:2019-06-18 18:42:53
【问题描述】:

我正在学习 Go,但很难理解为什么我的应用无法正常退出。使用下面的代码 sn-p 我得到了正确的结果,但是在读取最后一个文件后 main 永远不会退出。据我所知,这是因为它在某个地方是一个开放的渠道,但我无法弄清楚为什么以及如何做到这一点。

这个应用程序的要点是获取一个 PDF 文件数组并读出其中的某个字符串。

package main

import (
    "fmt"
    "os"
)

type PDF struct {
    filename string
    code string
    error  error
}

func (p *PDF) GetCode() string {
    return p.code
}

func main() {
    jobs := make(chan PDF)
    results := make(chan PDF)

    for w := 0; w < 8; w++ {
        go worker(jobs, results)
    }

    // PDF files to read.
    pdfs := []string{"test.pdf", "test2.pdf", "test3.pdf"}

    for _, file := range pdfs {
        go func(file string) {
            jobs <- PDF{filename: file}
        }(file)
    }
    defer close(jobs)

    for i := range results {
        fmt.Printf("%s ", i.GetCode())
    }
}

func worker(jobs <-chan PDF, results chan<- PDF) {
    for file := range jobs {
        fmt.Printf("Processing %s\n", file.filename)
        code, err := outputPdfText(file.filename)
        results <- PDF{filename: file.filename, code: code, error: err}
    }
}

func outputPdfText(inputPath string) (string, error) {
    // Code that reads PDF and returns value
    [...]
}

【问题讨论】:

    标签: go


    【解决方案1】:

    您的代码有死锁。等待处理完成的一个好方法是使用sync.WaitGroup。每次向工作人员添加作业时添加 1,然后在 goroutine 中调用 wg.done() 以表示作业已完成。当等待组上的作业计数为 0 时,您的代码将正确退出。这是一个例子:

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    type PDF struct {
        filename string
        code     string
        error    error
    }
    
    func (p *PDF) GetCode() string {
        return p.code
    }
    
    var wg sync.WaitGroup
    
    func main() {
    
        jobs := make(chan PDF)
        results := make(chan PDF)
    
        for w := 0; w < 8; w++ {
            go worker(jobs, results)
        }
    
        // PDF files to read.
        pdfs := []string{"test.pdf", "test2.pdf", "test3.pdf"}
    
        defer func() { close(results) }()
        for _, file := range pdfs {
            wg.Add(1)
            jobs <- PDF{filename: file}
        }
    
        go func() {
            for i := range results {
                fmt.Printf("%s", i.GetCode())
            }
        }()
        wg.Wait()
        close(jobs)
    }
    
    func worker(jobs <-chan PDF, results chan<- PDF) {
        for file := range jobs {
            fmt.Printf("Processing %s\n", file.filename)
            code, err := outputPdfText(file.filename)
            results <- PDF{filename: file.filename, code: code, error: err}
            wg.Done()
        }
    }
    
    func outputPdfText(inputPath string) (string, error) {
        // Code that reads PDF and returns value
        return "", nil
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-14
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-18
      相关资源
      最近更新 更多