将指针传递给bufio.Scanner()

问题描述 投票:0回答:1

为免我提供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),这是否可行?
go concurrency memory-mapped-files
1个回答
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
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.