Welcome To Golang By Example

Write to a file in Go (Golang)

There are different ways of writing a file in GO. Let’s examine this in detail through different examples which illustrates how to write line by line to a file.

Buffered write using bufio package

bufio package can be used to do a buffered write in Go. It has a default buffer size of 4096 bytes however a custom buffer size can also be specified. The main advantage of buffered write is that it keeps the data to be written in the buffer and thus minimizes the number of times we have to do the IO operation. It does a write when

If there is no buffer then there will be IO write on every line. Let’s see an example of a write to a file. We are using writer.Available() and writer.Buffered() to print the available and used buffer size respectively.

Example: With Default Buffer Size of 4096 bytes

It will write to temp.txt in the current directory. Write happens at the end when writer.Flush() is called as buffer never really gets full in between.

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    file, err := os.Create("./temp.txt")
    if err != nil {
        log.Fatal(err)
    }
    writer := bufio.NewWriter(file)
    linesToWrite := []string{"This is an example", "to show how", "to write to a file", "line by line."}
    for _, line := range linesToWrite {
        bytesWritten, err := writer.WriteString(line + "\n")
        if err != nil {
            log.Fatalf("Got error while writing to a file. Err: %s", err.Error())
        }
        fmt.Printf("Bytes Written: %d\n", bytesWritten)
        fmt.Printf("Available: %d\n", writer.Available())
        fmt.Printf("Buffered : %d\n", writer.Buffered())
    }
    writer.Flush()
}

Output:

Bytes Written: 19
Available: 4077
Buffered : 19
Bytes Written: 12
Available: 4065
Buffered : 31
Bytes Written: 19
Available: 4046
Buffered : 50
Bytes Written: 14
Available: 4032
Buffered : 64

Example: With Custom Buffer Size of 10 bytes

We can also create a custom buffer size for our writer using bufio.NewWriterSize(). In the below example, we create a write with a custom buffer size of 10 bytes. If you carefully notice the bytes “Available” and “Buffered” in output, you will find that writes to file keep happening in between when the buffer is full and at the end when writer.Flush() is called.

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
)

//Write file using bufio writer
func main() {
    file, err := os.Create("./temp  .txt")
    if err != nil {
        log.Fatal(err)
    }
    writer := bufio.NewWriterSize(file, 10)
    linesToWrite := []string{"This is an example", "to show how", "to write to a file", "line by line."}
    for _, line := range linesToWrite {
        bytesWritten, err := writer.WriteString(line + "\n")
        if err != nil {
            log.Fatalf("Got error while writing to a file. Err: %s", err.Error())
        }
        fmt.Printf("Bytes Written: %d\n", bytesWritten)
        fmt.Printf("Available: %d\n", writer.Available())
        fmt.Printf("Buffered : %d\n", writer.Buffered())
    }
    writer.Flush()
}

Output:

Bytes Written: 19
Available: 1
Buffered : 9
Bytes Written: 12
Available: 9
Buffered : 1
Bytes Written: 19
Available: 0
Buffered : 10
Bytes Written: 14
Available: 6
Buffered : 4

Using file.Write()

It does not maintain any buffer and writes to the file immediately as soon as the write is called. See the example below

package main

import (
    "log"
    "os"
)


func main() {
    file, err := os.Create("./test.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    linesToWrite := []string{"This is an example", "to show how", "to write to a file", "line by line."}
    for _, line := range linesToWrite {
        file.WriteString(line + "\n")
    }
}

Using ioutil.WriteFile()

ioutil.WriteFile() is kind of a shortcut to writing to a file. It takes in three-parameter – (1) file (2) The string to be written (3) Permission mode of the file. The third parameter is used to create a file with that permission if the file doesn’t already exist. One calling ioutil.WriteFile(), it will

See below example: If temp.txt doesn’t exist then it will create a new temp.txt file with permission 0777

package main

import (
    "io/ioutil"
    "log"
)

func main() {
    linesToWrite := "This is an example to show how to write to file using ioutil"
    err := ioutil.WriteFile("temp.txt", []byte(linesToWrite), 0777)
    if err != nil {
        log.Fatal(err)
    }
}