I'm currently available for contract work & technical writing opportunities. Hire me

How to rewind a file pointer in Go

When you open an os.File and read some or all its contents, the file pointer offset will be set to the last line that was read. If you want to reset the pointer to the beginning of the file, you need to call the Seek() method on the file.

func main() {
	file, err := os.Open("index.html")
	if err != nil {
		log.Fatal(err)
	}

	scanner := bufio.NewScanner(file)

	// iterate over each line in the file
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
	}

	if scanner.Err() != nil {
		log.Println(scanner.Err())
	}

	// Read the entire file and print to the standard output
	b, err := io.ReadAll(file)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(b)) // prints an empty string
}

After iterating over the entire file in the above example, the file pointer offset is exhausted so attempting to read from it a second time yields an empty string. To fix this, you need to call the Seek() method as shown below:

main.go
func main() {
	file, err := os.Open("index.html")
	if err != nil {
		log.Fatal(err)
	}

	scanner := bufio.NewScanner(file)

	// iterate over each line in the file
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
	}

	if scanner.Err() != nil {
		log.Println(scanner.Err())
	}

	// call the Seek method first
	_, err = file.Seek(0, io.SeekStart)
	if err != nil {
		log.Fatal(err)
	}

	// Read the entire file and print to the standard output
	b, err := io.ReadAll(file)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(b)) // this works correctly now
}

Thanks for reading, and happy coding!