Question

How to Read an Entire File Into a String in Go

gostringfile

Question

I have many small files and do not want to read them line by line.

Is there a function in Go that reads an entire file into a string variable?

Short Answer

By the end of this page, you will understand how to read a complete file into memory in Go and convert it into a string. You will also learn when this approach is appropriate, how to handle errors safely, and what alternatives to use when files are too large to load all at once.

Concept

In Go, a file is usually read as a slice of bytes ([]byte) because files contain raw data. If the file contains text, you can convert those bytes into a string.

The most common beginner-friendly way to read an entire file is with the standard library function:

data, err := os.ReadFile("example.txt")

This returns the full file contents as []byte. You can then convert it to a string:

content := string(data)

This matters because many programs need the full contents of a file at once, such as:

  • loading configuration files
  • reading templates
  • parsing JSON
  • working with small text files
  • processing test fixtures

Reading the whole file at once is simple and convenient, but it should mainly be used for small or reasonably sized files. For very large files, streaming or scanning line by line is usually better to avoid using too much memory.

Mental Model

Think of a file like a sealed envelope.

  • os.ReadFile() opens the envelope and pulls out everything at once.
  • The result is raw paper content as bytes ([]byte).
  • Converting to string is like saying, "Treat these bytes as readable text."

This is convenient when the envelope is small. If the envelope is huge, dumping everything onto your desk at once can be messy and inefficient. In that case, reading piece by piece is better.

Take Quiz

Syntax and Examples

Basic syntax

data, err := os.ReadFile("notes.txt")
if err != nil {
    // handle error
}

content := string(data)

Complete example

package main

import (
    "fmt"
    "os"
)

func main() {
    data, err := os.ReadFile("message.txt")
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }

    content := string(data)
    fmt.Println(content)
}

What this does

  • os.ReadFile("message.txt") reads the whole file into memory.
  • data is a []byte.
  • string(data) converts those bytes into a Go string.
  • If the file does not exist or cannot be opened, err will contain the problem.

If you only need bytes

If you are going to pass the contents to something that expects bytes, you may not need conversion at all:

data, err := os.ReadFile("data.json")
if err != nil {
    return
}

fmt.Printf("Read %d bytes\n", len(data))

Older code you may still see

In older Go code, you may see ioutil.ReadFile:

data, err := ioutil.ReadFile("message.txt")
content := string(data)

Modern Go uses os.ReadFile instead.

Step by Step Execution

Consider this example:

package main

import (
    "fmt"
    "os"
)

func main() {
    data, err := os.ReadFile("hello.txt")
    if err != nil {
        fmt.Println("Failed to read file:", err)
        return
    }

    text := string(data)
    fmt.Println(text)
}

Assume hello.txt contains:

Hello, Go!

Step by step

  1. The program starts in main().
  2. os.ReadFile("hello.txt") opens the file and reads all of its contents.
  3. The contents are stored in data as bytes.
    • For example, data might represent the bytes for Hello, Go!.
  4. If something goes wrong, err is not nil.
    • The program prints the error and stops early.
  5. If reading succeeds, string(data) converts the bytes into text.
  6. The result is stored in text.
  7. fmt.Println(text) prints the file content.

Result

Hello, Go!

Real World Use Cases

Reading a whole file into a string is useful when the file is small and you need all of it at once.

Common uses

  • Configuration files
    • Read a JSON, YAML, or TOML file before parsing it.
  • HTML or email templates
    • Load a template file into memory for rendering.
  • SQL scripts
    • Read a .sql file and execute its contents.
  • Test data
    • Load fixture files for unit tests.
  • Markdown or text content
    • Read documentation, blog content, or prompts.

Example: reading a JSON file before parsing

data, err := os.ReadFile("config.json")
if err != nil {
    return err
}

jsonText := string(data)
fmt.Println(jsonText)

In practice, you might skip converting to string if the parser accepts []byte.

Take Quiz

Real Codebase Usage

In real Go projects, developers often read full files for convenience when the files are expected to be small.

Common patterns

Validate early

data, err := os.ReadFile(path)
if err != nil {
    return fmt.Errorf("read %s: %w", path, err)
}

This is a common early return pattern for error handling.

Convert only when needed

content := string(data)

If a library accepts []byte, keep the bytes and avoid unnecessary conversion.

Wrap errors with context

data, err := os.ReadFile(path)
if err != nil {
    return fmt.Errorf("could not load template file %q: %w", path, err)
}

This makes debugging easier in larger codebases.

Helper function pattern

func mustReadTextFile(path string) string {
    data, err := os.ReadFile(path)
    if err != nil {
        panic(err)
    }
    return string(data)
}

This kind of helper may appear in tests or startup code, though panic is usually avoided in normal application logic.

Use streaming for large files

Real applications often switch to bufio.Scanner or bufio.Reader when files are large or need incremental processing.

Common Mistakes

1. Forgetting to handle the error

Broken code:

data, _ := os.ReadFile("missing.txt")
content := string(data)
fmt.Println(content)

Why it is a problem:

  • If the file cannot be read, you silently ignore the failure.
  • This makes bugs harder to find.

Better:

data, err := os.ReadFile("missing.txt")
if err != nil {
    fmt.Println("Error:", err)
    return
}

2. Assuming every file is text

Broken idea:

content := string(data)

This is only meaningful if the file actually contains text. Binary files like images or PDFs should usually stay as []byte.

3. Using this for very large files

Reading the whole file into memory can waste RAM.

Avoid this approach when:

  • files are very large
  • you only need part of the file
  • you want to process line by line

4. Using outdated package names in new code

Older examples may use:

ioutil.ReadFile("file.txt")

Prefer:

os.ReadFile("file.txt")

5. Confusing bytes and strings

Broken code:

var content string = os.ReadFile("file.txt")

Why it fails:

  • os.ReadFile returns ([]byte, error), not a string.

Correct version:

data, err := os.ReadFile("file.txt")
if err != nil {
    return
}
content := string(data)

Comparisons

ApproachBest forReturnsNotes
os.ReadFileSmall whole-file reads[]byteSimplest way to read entire file
bufio.ScannerReading line by linetokens/linesGood for text processing
bufio.ReaderStreaming larger text inputchunks/stringsMore flexible than Scanner
os.Open + manual readsLarge or custom reading logicbytes read into bufferUseful for full control

os.ReadFile vs line-by-line reading

  • Use os.ReadFile when you want the entire file now.
  • Use line-by-line reading when:
    • the file is large
    • you want to process one line at a time
    • memory efficiency matters

[]byte vs string

TypeUse whenMutable?
[]byteWorking with raw file data or APIs that accept bytesYes
stringWorking with text contentNo

In Go, files are read as bytes first. Converting to string is an extra step when the contents are textual.

Take Quiz

Cheat Sheet

Quick reference

Read entire file

data, err := os.ReadFile("file.txt")
if err != nil {
    return
}

Convert file bytes to string

content := string(data)

Full pattern

data, err := os.ReadFile(path)
if err != nil {
    return err
}
text := string(data)

When to use it

  • Small text files
  • Config files
  • Templates
  • Test fixtures

When not to use it

  • Very large files
  • Streaming input
  • Binary data you do not want as text

Important rules

  • os.ReadFile returns []byte, error
  • Always check err
  • Convert to string only if the file is text
  • Prefer os.ReadFile over old ioutil.ReadFile in modern Go

FAQ

Is there a built-in Go function to read a whole file?

Yes. Use os.ReadFile() to read the entire file into memory.

How do I store the file contents in a string in Go?

Read the file as bytes, then convert it:

data, err := os.ReadFile("file.txt")
content := string(data)

Why does os.ReadFile return []byte instead of string?

Because files can contain any kind of data, not just text. Bytes are the most general representation.

Should I use os.ReadFile for large files?

Usually no. For large files, streaming with bufio.Scanner, bufio.Reader, or manual reads is often better.

What happened to ioutil.ReadFile?

It appears in older Go code, but modern Go code should use os.ReadFile.

Can I read JSON or YAML files this way?

Yes. This is very common for small config files. Some parsers accept []byte directly, so conversion to string may not be necessary.

What if the file does not exist?

os.ReadFile returns an error. Always check the err value before using the data.

Take Quiz

Mini Project

Description

Build a small Go program that loads a text file and prints its contents along with the number of characters it contains. This demonstrates how to read a full file into memory, convert bytes to a string, and handle file errors properly.

Goal

Create a Go program that reads an entire text file into a string and prints both the content and its length.

Requirements

  1. Read a file from disk using the Go standard library.
  2. Handle the case where the file cannot be opened or read.
  3. Convert the file contents from []byte to string.
  4. Print the file contents.
  5. Print the number of characters in the resulting string.
Take Quiz

Keep learning

Related questions

View more