Golang 2015-如何关闭打开文件功能之外的文件?

I'm trying to read lines in files. I'd like to easily open a file, and parse through the lines one at a time, and remove some boilerplate opening and closing. I'm passing back a pointer to the 'scanner'. Is this just a dumb approach? Has the scanner already read the contents because of the Split? Are there better ways of doing this? Any insight regarding best practices are appreciated.

    func main() {
            var path string
            if len(os.Args) > 1 {
                    err, scanner := fileScanner(path)
                    if err == nil {
                            // Go through file line by line.
                            for scanner.Scan() {
                                    fmt.Println(scanner.Text())
                                    // or do other stuff
                            }
                            // so how do I make sure to close the file?
                    }
            }
    }

    // Return a scanner for a file.
    func fileScanner(path string) *bufio.Scanner {
            file, err := os.Open(path)
            if err != nil {
                    return err
            }
            //defer file.Close()
            scanner := bufio.NewScanner(file)
            scanner.Split(bufio.ScanLines)
            return err, scanner
    }

I think the simplest solution is just not to open the file in your fileScanner function.

If it's really important for you to extract these operations out of your main function then consider creating a new struct type that holds both your scanner and your file pointer and then you can define methods on that type to open, close and get the scanner. Something along these lines:

type fileScanner struct {
    File    *os.File
    Scanner *bufio.Scanner
}

func NewFileScanner() *fileScanner {
    return &fileScanner{}
}

func (f *fileScanner) Open(path string) (err error) {
    f.File, err = os.Open(path)
    return err
}

func (f *fileScanner) Close() error {
    return f.File.Close()
}

func (f *fileScanner) GetScanner() *bufio.Scanner {
    if f.Scanner == nil {
        f.Scanner = bufio.NewScanner(f.File)
        f.Scanner.Split(bufio.ScanLines)
    }
    return f.Scanner
}

func main() {
    var path string
    if len(os.Args) > 1 {
        fscanner := NewFileScanner()
        err := fscanner.Open(path)
        if err == nil {
            defer fscanner.Close()
            scanner := fscanner.GetScanner()
            // Go through file line by line.
            for scanner.Scan() {
                fmt.Println(scanner.Text())
                // or do other stuff
            }

        }
    }
}

Which is rather a lot of work for this purpose. Other alternatives are to return the file from your function (though you should handle panics to avoid any possible leaks) or to return a cleanup function.