从频道读取后主要不退出

  • 本文关键字:退出 频道 读取 go
  • 更新时间 :
  • 英文 :


我正在学习 Go,但很难理解为什么我的应用程序无法正常退出。使用下面的代码片段,我得到了正确的结果,但在读取最后一个文件后,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 %sn", 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
    [...]
}

您的代码存在死锁。等到处理完成的一个好方法是使用 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 %sn", 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
}

最新更新