How to Check If a File Exists in Go

Use `os.Stat()` to check if a file exists by examining the returned error; if the error is `nil`, the file exists, and if it is `os.IsNotExist(err)`, the file is missing.

Use os.Stat() to check if a file exists by examining the returned error; if the error is nil, the file exists, and if it is os.IsNotExist(err), the file is missing. This approach is preferred over os.Open() because it avoids holding an open file handle just to check existence.

Here is a robust pattern using os.Stat:

package main

import (
	"fmt"
	"os"
)

func main() {
	filename := "data.txt"
	
	// Check if file exists
	_, err := os.Stat(filename)
	if os.IsNotExist(err) {
		fmt.Println("File does not exist.")
		return
	}
	if err != nil {
		// Handle other errors (e.g., permission denied)
		fmt.Printf("Error checking file: %v\n", err)
		return
	}

	fmt.Println("File exists.")
}

If you need to distinguish between a regular file and a directory, you can inspect the FileInfo returned by os.Stat:

fi, err := os.Stat(filename)
if err != nil {
	if os.IsNotExist(err) {
		// File missing
		return
	}
	// Other error handling
	return
}

// Check if it is a regular file
if fi.Mode().IsRegular() {
	fmt.Println("It is a regular file.")
} else if fi.IsDir() {
	fmt.Println("It is a directory.")
}

Avoid using os.Open() solely for existence checks. While os.Open() returns an error if the file is missing, it also acquires a file descriptor that you must explicitly close. If you open the file just to check existence and then close it immediately, you are performing unnecessary system calls. os.Stat() is lighter and semantically clearer for this specific task.

Be careful with race conditions. If you check for existence and then immediately try to create or write to the file, another process could delete or create the file in the tiny window between the check and the action. In such cases, it is often better to attempt the operation directly (like os.Create or os.OpenFile with flags) and handle the specific error if it fails, rather than checking first. However, for simple existence checks where you don't immediately mutate the file, os.Stat with os.IsNotExist is the standard, idiomatic solution.