为免我提供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)
,这是否可行?答案 0 :(得分:4)
您在使用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
}
}