Skip to main content
Go Language Fundamentals for Beginners to Advanced
CHAPTER 18 Beginner

File Handling in Go

Updated: May 17, 2026
5 min read

# CHAPTER 18

File Handling in Go

1. Introduction

Whether you are writing server logs, reading a JSON configuration file, or processing an uploaded image, your backend application must interact with the Operating System's file system. Go provides a fast, robust set of tools primarily located in the os and io packages to handle File Input/Output (I/O).

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Create and write to a new file.
  • Read data from an existing file.
  • Use defer to ensure files are closed safely.
  • Understand basic file permissions (e.g., 0644).
  • Delete files from the system.

3. Writing to a File

To create or write to a file, we use the os.WriteFile function. It requires three things: the filename, the data (as a slice of bytes []byte), and the file permissions.
go
123456789101112131415161718192021
package main

import (
    "fmt"
    "os"
)

func main() {
    message := "Welcome to File Handling in Go!"
    // Convert string to a slice of bytes []byte
    data := []byte(message) 

    // 0644 means: Owner can Read/Write. Others can only Read.
    err := os.WriteFile("notes.txt", data, 0644)
    
    if err != nil {
        fmt.Println("Error writing file:", err)
        return
    }
    fmt.Println("File created successfully!")
}

4. Reading from a File

Reading the entire contents of a file into memory is extremely simple using os.ReadFile.
go
12345678910111213
func main() {
    // Returns the file contents as a slice of bytes
    data, err := os.ReadFile("notes.txt")
    
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }

    // Convert the bytes back to a string to print it
    fmt.Println("File Content:")
    fmt.Println(string(data))
}

5. Appending and Advanced File Operations (os.OpenFile)

os.WriteFile overwrites the entire file every time. If you are building a server logger, you want to *append* to the end of the file. To do this, we must open the file manually with specific flags, write to it, and then explicitly close it.

The Golden Rule of File I/O: If you open a file, you MUST close it. Leaving files open causes "Memory Leaks" and file locking issues. We use the defer keyword to guarantee the file closes the moment the function finishes.

go
1234567891011121314151617
func main() {
    // Open file with flags: Append (O_APPEND), Create if it doesn't exist (O_CREATE), Write-Only (O_WRONLY)
    file, err := os.OpenFile("server.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("Failed to open file:", err)
        return
    }
    
    // CRITICAL: Schedule the file to close when main() finishes!
    defer file.Close()

    // Write a new line
    logEntry := "User logged in at 10:00 AM\n"
    file.WriteString(logEntry)
    
    fmt.Println("Log updated!")
}

6. Deleting a File

To delete a file, use os.Remove().
go
12345678
func main() {
    err := os.Remove("notes.txt")
    if err != nil {
        fmt.Println("Could not delete file:", err)
        return
    }
    fmt.Println("File deleted.")
}

7. Mini Project: Notes CLI

Let's build a mini-app that asks the user for a note and saves it to a file.
go
123456789101112131415161718192021222324
package main

import (
    "fmt"
    "os"
)

func main() {
    var note string
    fmt.Print("Enter a note to save: ")
    // NOTE: Scanln only reads up to the first space. 
    // In a real app, you would use bufio.NewReader for full sentences.
    fmt.Scanln(&note) 

    file, err := os.OpenFile("my_notes.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()

    file.WriteString(note + "\n")
    fmt.Println("Note saved securely!")
}

8. Common Mistakes

  • Forgetting defer file.Close(): This is the #1 mistake beginners make. If a server opens 10,000 files and never closes them, the operating system will crash the server for exceeding file handle limits.
  • Reading Massive Files into Memory: os.ReadFile loads the *entire* file into RAM. If the file is a 50GB database dump, your program will run out of memory and crash. (For massive files, use bufio.NewReader or os.File.Read in chunks).

9. Best Practices

  • Always check errors: Trying to read a file that doesn't exist will crash your logic. Always write if err != nil after interacting with the file system.

10. Exercises

  1. 1. Write a program that creates a file called hello.txt and writes your name into it.
  1. 2. Read the file and print the output.
  1. 3. Use os.Remove to delete the file.

11. MCQs with Answers & Explanations

Question 1

Which package provides the core functionality to interact with the Operating System's file system?

Question 2

os.WriteFile requires data to be passed in what format?

Question 3

What does the file permission 0644 generally mean in Unix systems?

Question 4

What is the danger of using os.ReadFile on a 10GB video file?

Question 5

When manually opening a file with os.OpenFile, what is the most critical step to prevent memory leaks?

Question 6

Which keyword should you use to guarantee file.Close() runs even if an error/panic occurs later in the function?

Question 7

If you want to add text to the END of a file without destroying existing data, which flag must you use in os.OpenFile?

Question 8

What happens if you try to open a file that doesn't exist without using the os.OCREATE flag?

Question 9

How do you delete a file in Go?

Question 10

How do you convert a slice of bytes data back into human-readable text?

12. Interview Preparation

Interview Questions:
  1. 1. Why is the defer keyword heavily used in Go file handling?
  1. 2. Explain the difference between os.WriteFile and opening a file with os.O_APPEND.
  1. 3. How would you handle reading a file that is significantly larger than the available RAM?

13. Summary

Interacting with the file system allows your Go applications to persist data permanently. Functions like os.ReadFile and os.WriteFile make basic I/O trivial, while os.OpenFile provides deep, granular control over how files are modified. Always remember to respect the OS by checking your errors and using defer file.Close() to release resources.

14. Next Chapter Recommendation

We have mastered the foundational concepts of Go! Now, we enter the most exciting phase of the course. Go is famous for its ability to handle thousands of tasks simultaneously. In Chapter 19: Goroutines and Concurrency, you will learn how to unlock the full power of your multi-core processor.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·