✍️ Write to a file in Go

April 29, 2021
introduction file

Go has excellent built-in support for file operations. Using the os package, you can easily open, read from, write to and close the file. In this example, we focus on writing data to a file. We show you how you can write text and binary data in different ways - entire data at once, line by line, as an array of bytes in a specific place, or in a buffered manner.

Write the entire content to a file at once

The shortest way of writing data to a file is to use the os.WriteFile() function. It takes three input parameters:

  1. Path to the file that we want to write to
  2. Byte data which we want to write to the file
  3. Permission bits of the file that will be created

Creating and closing the file is done by the function itself, so it’s no need to create or close the file before and after writing.

If you are using the Go version earlier than 1.16, you will find the WriteFile() function in the ioutil package.

package main

import (
    "log"
    "os"
)

func main() {
    if err := os.WriteFile("file.txt", []byte("Hello GOSAMPLES!"), 0666); err != nil {
        log.Fatal(err)
    }
}

Write text data to a file line by line

If you have your file’s lines in separate variables, an array, or want to do some processing before writing a single line, you can write the data line by line using the func (*File) WriteString() method. All you need to do is create a file, write your strings to it, and finally close the file.

package main

import (
    "log"
    "os"
)

var lines = []string{
    "Go",
    "is",
    "the",
    "best",
    "programming",
    "language",
    "in",
    "the",
    "world",
}

func main() {
    // create file
    f, err := os.Create("file.txt")
    if err != nil {
        log.Fatal(err)
    }
    // remember to close the file
    defer f.Close()

    for _, line := range lines {
        _, err := f.WriteString(line + "\n")
        if err != nil {
            log.Fatal(err)
        }
    }
}

Write byte data to a file

As with writing strings line by line, we can also write byte data using the func (*File) Write() method or func (*File) WriteAt() if you want to write data at a given offset.

package main

import (
    "log"
    "os"
)

var bytes = []byte{
    0x47, // G
    0x4f, // O
    0x20, // <space>
    0x20, // <space>
    0x20, // <space>
    0x50, // P
    0x4c, // L
    0x45, // E
    0x53, // S
}

var additionalBytes = []byte{
    0x53, // S
    0x41, // A
    0x4d, // M
}

func main() {
    // create file
    f, err := os.Create("file.txt")
    if err != nil {
        log.Fatal(err)
    }
    // remember to close the file
    defer f.Close()

    // write bytes to the file
    _, err = f.Write(bytes)
    if err != nil {
        log.Fatal(err)
    }

    // write additional bytes to the file, start at index 2
    _, err = f.WriteAt(additionalBytes, 2)
    if err != nil {
        log.Fatal(err)
    }
}

Write formatted strings to a file

In addition to the File methods, we can use fmt.Fprintln() function to write data to a file. This function formats its operands, adds spaces between them, a new line at the end, and writes the output to the writer (first argument). It’s great for simple line formatting or writing the string representation of a struct to a file.

package main

import (
    "fmt"
    "log"
    "os"
)

var lines = []string{
    "Go",
    "is",
    "the",
    "best",
    "programming",
    "language",
    "in",
    "the",
    "world",
}

func main() {
    // create file
    f, err := os.Create("file.txt")
    if err != nil {
        log.Fatal(err)
    }
    // remember to close the file
    defer f.Close()

    for _, line := range lines {
        _, err := fmt.Fprintln(f, "*", line, "*")
        if err != nil {
            log.Fatal(err)
        }
    }
}

Write to a file using a buffered writer

If you frequently write a small amount of data to a file, it can hurt the performance of your program. Each write is a costly system call, and if you don’t need immediate file updates, it is a better idea to group these small writes into one. To do this, we can use bufio.Writer structure. Its writing functions do not save data directly to the file but keep it until the buffer underneath is full (default size is 4096 bytes) or the Flush() method is called. So make sure to call Flush() after the completed write to save the remaining data to the file.

package main

import (
    "bufio"
    "log"
    "os"
)

var lines = []string{
    "Go",
    "is",
    "the",
    "best",
    "programming",
    "language",
    "in",
    "the",
    "world",
}

func main() {
    // create file
    f, err := os.Create("file.txt")
    if err != nil {
        log.Fatal(err)
    }
    // remember to close the file
    defer f.Close()

    // create new buffer
    buffer := bufio.NewWriter(f)

    for _, line := range lines {
        _, err := buffer.WriteString(line + "\n")
        if err != nil {
            log.Fatal(err)
        }
    }

    // flush buffered data to the file
    if err := buffer.Flush(); err != nil {
        log.Fatal(err)
    }
}

✒️ Write to a CSV file in Go

Learn how to write data to a CSV or TSV file
introduction file

🙌 Case-insensitive string comparison in Go

Learn how to compare strings in a case-insensitive manner
introduction strings

🏁 Check if a string starts with a substring in Go

Learn how to use strings.HasPrefix() function
introduction strings