桃花长相依
此代码的 2 个主要问题是您只需要在完成后关闭频道wg.Wait()。您可以在单独的 goroutine 中执行此操作,如下所示由于pathsearchPaths func 中的 var 作为 for 循环逻辑的一部分被多次重新分配,因此not a good practice to use that var directly in the goroutines更好的方法是将其作为参数传递。package mainimport ( "fmt" "io/fs" "io/ioutil" "log" "os" "path/filepath" "strings" "sync")type SearchResult struct { line string lineNumber int}type Display struct { filePath string SearchResult}var wg sync.WaitGroupfunc (d Display) PrettyPrint() { fmt.Printf("Line Number: %v\nFilePath: %v\nLine: %v\n\n", d.lineNumber, d.filePath, d.line)}func searchLine(pattern string, line string, lineNumber int) (SearchResult, bool) { if strings.Contains(line, pattern) { return SearchResult{lineNumber: lineNumber + 1, line: line}, true } return SearchResult{}, false}func splitIntoLines(file string) []string { lines := strings.Split(file, "\n") return lines}func fileFromPath(path string) string { fileContent, err := ioutil.ReadFile(path) if err != nil { log.Fatal(err) } return string(fileContent)}func getRecursiveFilePaths(inputDir string) []string { var paths []string err := filepath.Walk(inputDir, func(path string, info fs.FileInfo, err error) error { if err != nil { fmt.Printf("prevent panic by handling failure accessing a path %q: %v\n", path, err) return err } if !info.IsDir() { paths = append(paths, path) } return nil }) if err != nil { fmt.Printf("Error walking the path %q: %v\n", inputDir, err) } return paths}func searchPaths(paths []string, pattern string) chan Display { out := make(chan Display) for _, path := range paths { wg.Add(1) go func(p string, w *sync.WaitGroup) { // as path var is changing value in the loop, it's better to provide it as a argument in goroutine defer w.Done() for _, display := range searchFile(p, pattern) { out <- display } }(path, &wg) } return out}func searchFile(path string, pattern string) []Display { var out []Display input := fileFromPath(path) lines := splitIntoLines(input) for index, line := range lines { if searchResult, ok := searchLine(pattern, line, index); ok { out = append(out, Display{path, searchResult}) } } return out}func main() { pattern := os.Args[1] dirPath := os.Args[2] paths := getRecursiveFilePaths(dirPath) out := searchPaths(paths, pattern) go func(){ wg.Wait() // waiting before closing the channel close(out) }() count := 0 for d := range out { fmt.Println(count) d.PrettyPrint() count += 1 }}