This page looks best with JavaScript enabled

Go writing files

 ·  🎃 kr0m

Writing files is one of the most common operations in Go. In this article, we will learn about the different possibilities Go offers for doing so.

The article is divided into several sections:


If you are new to the world of Go, I recommend the following previous articles:


Write a string:

The code is quite self-explanatory.

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.Create("test.txt")
    if err != nil {
        fmt.Println(err)
        return
    }

    l, err := f.WriteString("Hello World\n")
    if err != nil {
        fmt.Println(err)
        f.Close()
        return
    }

    fmt.Println(l, "bytes written successfully")

    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
}
12 bytes written successfully
cat test.txt
Hello World

Write bytes:

Writing a sequence of bytes is very similar to the previous example; you just need to create the byte slice and write it.

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.Create("test.txt")
    if err != nil {
        fmt.Println(err)
        return
    }

    d2 := []byte{72, 101, 108, 108, 111, 32, 66, 121, 116, 101, 115, 10}
    n2, err := f.Write(d2)
    if err != nil {
        fmt.Println(err)
        f.Close()
        return
    }

    fmt.Println(n2, "bytes written successfully")

    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
}
12 bytes written successfully
cat test.txt
Hello Bytes

Write line by line:

To write line by line, we will create a slice with each of the lines and write them using the fmt.Fprintln() function, which takes the file descriptor as the first input parameter and the line to write as the second parameter.

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.Create("test.txt")
    if err != nil {
        fmt.Println(err)
        f.Close()
        return
    }

    d := []string{"Welcome to the world of Go1.", "Go is a compiled language.", "It is easy to learn Go."}

    for _, v := range d {
        fmt.Fprintln(f, v)
        if err != nil {
            fmt.Println(err)
            return
        }
    }

    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("File written successfully")
}
File written successfully
cat test.txt
Welcome to the world of Go1.
Go is a compiled language.
It is easy to learn Go.

Append content:

To append content to a previously existing file, you should not use the os.Create() function but instead os.OpenFile(). You must specify the file, the access mode, and the permissions. These permissions will be used if the file does not exist and O_CREATE mode is specified. If the file already exists, the existing permissions are retained. Even when O_CREATE mode is not used, as in this case, the function requires you to specify permissions.

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println(err)
        return
    }

    newLine := "File handling is easy."
    _, err = fmt.Fprintln(f, newLine)
    if err != nil {
        fmt.Println(err)
        f.Close()
        return
    }

    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("File appended successfully")
}
File appended successfully
cat test.txt
Already existent line
File handling is easy.

Concurrent writes:

Writing in parallel is as simple as calling the function responsible for writing using go routines ; you just need to remember to use a waitGroup to control when all of them have finished writing.

package main

import (
    "fmt"
    "os"
    "strconv"
    "sync"
)

func writeLine(f *os.File, newLine string, wg *sync.WaitGroup) {
    _, err := fmt.Fprintln(f, newLine)
    wg.Done()
    if err != nil {
        fmt.Println(err)
    }
}

func main() {
    f, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println(err)
        return
    }

    wg := sync.WaitGroup{}
    for i := 1; i <= 300; i++ {
        newLine := "Line: " + strconv.Itoa(i)
        wg.Add(1)
        go writeLine(f, newLine, &wg)
    }
    wg.Wait()

    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("File appended successfully")
}
File appended successfully
wc -l test.txt
     300 test.txt
If you liked the article, you can treat me to a RedBull here