我正在学习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 %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
[...]
}
答案 0 :(得分:2)
您的代码有死锁。等待处理完成的一个好方法是使用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
}