为免我提供an XY problem,我的目标是在多个goroutine as recommended之间共享一个内存映射文件。每个goroutine需要逐行遍历文件,所以我希望首先将完整的内容存储在内存中以加快速度。
我尝试的方法是将指针传递给bufio.Scanner
,但这不起作用。我认为这可能与需要将搜索位置设置回文件的开头有关,但它甚至不是第一次工作,我在文档中找不到这样的参数。我的尝试是创建这个函数,然后通过引用传递结果我打算在goroutine中运行的函数(现在,我不使用goroutines只是为了确保它完全正常工作,它没有)。
这是一个MWE:
// ... package declaration; imports; yada yada
func main() {
// ... validate path to file stored in filePath variable
filePath := "/path/to/file.txt"
// get word list scanner to be shared between goroutines
scanner := getScannerPtr(&filePath)
// pass to function (no goroutine for now, I try to solve one problem at a time)
myfunc(scanner)
}
func getScannerPtr(filePath *string) *bufio.Scanner {
f, err := os.Open(*filePath)
if err != nil {
fmt.Fprint(os.Stderr, "Error opening file\n")
panic(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanLines)
return scanner
}
func myfunc(scanner *bufio.Scanner) {
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// ... do something with line
}
}
我没有收到任何错误,它只是在我调用Scan()
时没有迭代文件,因此它永远不会在该块内部对文件的每一行做任何事情。请记住,我甚至没有使用并发,这只是我最终的目标,我想指出,以防影响我需要采取的方法。
Scan()
不起作用?go myfunc(scanner)
,这是否可行?你在使用Scanner
之前关闭了文件:
func getScannerPtr(filePath *string) *bufio.Scanner {
f, err := os.Open(*filePath)
if err != nil {
fmt.Fprint(os.Stderr, "Error opening file\n")
panic(err)
}
defer f.Close() // <--- Here
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanLines)
return scanner // <-- File gets closed, then Scanner that tries to read it is returned for further use, which won't work
}
因为Scanner
不暴露Close
,你需要解决这个问题;最快的可能是创建一个带有几个嵌入字段的简单自定义类型:
type FileScanner struct {
io.Closer
*bufio.Scanner
}
func getScannerPtr(filePath *string) *FileScanner {
f, err := os.Open(*filePath)
if err != nil {
fmt.Fprint(os.Stderr, "Error opening file\n")
panic(err)
}
scanner := bufio.NewScanner(f)
return &FileScanner{f, scanner}
}
func myfunc(scanner *FileScanner) {
defer scanner.Close()
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// ... do something with line
}
}