【发布时间】:2022-05-17 16:21:00
【问题描述】:
我编写了一个示例程序来进行文件搜索,它会搜索但最后失败
致命错误:所有 goroutine 都处于休眠状态 - 死锁!
goroutine 1 [chan 接收]: main.main() ~/Learning/golang/GoFileSearch/file_search.go:52 +0x2a7
我检查了许多 Waitgroups 的示例,这部分对我来说似乎没问题,我尝试将它作为参考传递给函数,但这也产生了相同的结果。
我错过了什么?
package main
import (
"bufio"
"flag"
"fmt"
"io/fs"
"log"
"os"
"strings"
"sync"
)
func main() {
searchTerm := flag.String("s", "", "Search string")
dirname := flag.String("dirname", ".", "Directory for search")
flag.Parse()
if len(*searchTerm) == 0 {
log.Fatal("enter search term")
}
dirInfo,err := os.Stat(*dirname)
if err != nil {
panic(err)
}
if !dirInfo.IsDir() {
panic("please enter a directory for dirname")
}
files, err := os.ReadDir(*dirname)
ch := make(chan string)
wg:= &sync.WaitGroup{}
defer close(ch)
for _, file := range files {
if file.IsDir() {
continue
}
wg.Add(1)
fmt.Println("Searching in "+*dirname + "/" + file.Name())
//search for the keyword in the file
go func() {
defer wg.Done()
search(*searchTerm, *dirname, file, ch)
}()
}
for name := range ch {
fmt.Println("Search term found in ->"+name)
}
wg.Wait()
fmt.Println("Done")
}
func search(searchTerm string,
dirname string,
fileEntry fs.DirEntry,
resultChan chan string) {
filePath := dirname + "/" + fileEntry.Name()
file, err := os.Open(filePath)
if err != nil {
log.Println(err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
// optionally, resize scanner's capacity for lines over 64K, see next example
for scanner.Scan() {
if strings.Contains(scanner.Text(), searchTerm) {
fmt.Println("Found")
resultChan <- fileEntry.Name()
return
}
}
}
如果有任何帮助,我将不胜感激
【问题讨论】:
-
ch永远不会关闭,所以你陷入了循环。 -
工人完成后关闭
ch。这是an answer that shows how to close the channel。 -
将文件循环参数传递给 goroutine。理由:github.com/golang/go/wiki/…。 goroutine 可能直到循环之后才会开始执行,因此搜索总是获取最后一个 files[] 值。
-
这个建议解决了我的问题,谢谢!!!但是我仍然不确定,为什么 defer close(ch) 没有成功?
-
如果文件没有
searchTerm,它将永远等待for name := range ch。所以结果打印循环也应该在 goroutine 中。
标签: go synchronization