The translation

Original address: golangbot.com/write-files…

In this tutorial, you’ll learn how to write data to a file using Go. We’ll also learn how to write files simultaneously.

This tutorial includes the following sections

  • Writes a string to a file
  • Writes bytes to a file
  • Write the data to the file line by line
  • Append to file
  • Write to file simultaneously

Please run all the programs for this tutorial on your local system, because Playground does not support file manipulation correctly.

Writes a string to a file

One of the most common file writes is writing a string to a file. That’s easy to do. It includes the following steps.

  1. Create a file
  2. Writes a string to a file

Let’s start coding right away.

package main

import (  
    "fmt"
    "os"
)

func main(a) {  
    f, err := os.Create("test.txt")
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    l, err := f.WriteString("Hello World")
    iferr ! =nil {
        fmt.Println(err)
        f.Close()
        return
    }
    fmt.Println(l, "bytes written successfully")
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        return}}Copy the code

On line 9, the create function creates a file named test.txt and truncates it if one already exists with that name. This function returns the file descriptor.

In line 14, we use WriteString to write the string Hello World to the file, which returns the number of bytes written and any Err.

Finally, we Close the file stream with Close

The above program will print:

11 bytes written successfully  
Copy the code

You can find the test.txt file in the program’s directory. You can open it with any text editor, and when you open it, you’ll see the text of Hello World.

Writes byte to a file

Writing bytes to a file is very similar to writing a string to a file. We can use the Write method to Write bytes to a file.

The following program slices bytes into a file.

package main

import (  
    "fmt"
    "os"
)

func main(a) {  
    f, err := os.Create("/home/naveen/bytes")
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    d2 := []byte{104.101.108.108.111.32.119.111.114.108.100}
    n2, err := f.Write(d2)
    iferr ! =nil {
        fmt.Println(err)
        f.Close()
        return
    }
    fmt.Println(n2, "bytes written successfully")
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        return}}Copy the code

In line 15 of the program above, we use the Write method to Write bytes slices to a file named bytes in the /home/naveen folder. Of course, you can also replace any other folder. The rest of the procedure is relatively simple. The program creates a bytes file and prints 11 bytes written successfully. When you open the file, you can see the Hello Bytes text content.

Write the data to the file line by line

Another common file operation involves writing strings to a file line by line. In this section, we will write a program to create a file with the following content.

Welcome to the world of Go.  
Go is a compiled language.  
It is easy to learn Go.  
Copy the code

Let’s start coding right away.

package main

import (  
    "fmt"
    "os"
)

func main(a) {  
    f, err := os.Create("lines")
    iferr ! =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)
        iferr ! =nil {
            fmt.Println(err)
            return
        }
    }
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    fmt.Println("file written successfully")}Copy the code

In line 9, we create a new file called Lines. In line 17 we loop through the array using the for range and write the line to the file using the Fprintln function. The Fprintln function takes IO. Writer as an argument and adds a new line, which is exactly what we want. Running the program will print the file that was successfully written and will create the file line in the current directory. The contents of the file line are provided below.

Welcome to the world of Go1.  
Go is a compiled language.  
It is easy to learn Go. 
Copy the code

Append to file

In this section, we append a line to the lines file created in the previous section. We will append File handling is easy to the end of the lines File

The file must be opened in append and write only mode. These flags are passed, and the arguments are passed to the Open function. After opening the file in append mode, we add the new line to the file.

package main

import (  
    "fmt"
    "os"
)

func main(a) {  
    f, err := os.OpenFile("lines", os.O_APPEND|os.O_WRONLY, 0644)
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    newLine := "File handling is easy."
    _, err = fmt.Fprintln(f, newLine)
    iferr ! =nil {
        fmt.Println(err)
                f.Close()
        return
    }
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    fmt.Println("file appended successfully")}Copy the code

In line 9, we open the file in append and write only mode. After the file has been successfully opened, we add a new line to the file at line 15 of the program. The program will print file appended successfully. After running the program, the contents of the Lines file will be:

Welcome to the world of Go1.  
Go is a compiled language.  
It is easy to learn Go.  
File handling is easy. 
Copy the code

Write to file simultaneously

When multiple Goroutines write concurrently to files, we end up in a race state. Therefore, channels should be used to coordinate concurrent writes to files.

We’ll write a program that creates 100 Goroutines. Each Goroutine generates a random number at the same time, so a total of one hundred random numbers are generated. These random numbers will be written to the file. We will solve this problem in the following ways.

  1. Creates a channel that will be used to read and write the generated random numbers.
  2. Create 100 producer Goroutines. Each Goroutine will generate a random number and write that random number to the channel.
  3. Create a consumer Goroutine that reads from the channel and writes the generated random number to a file. Therefore, we only have one goroutine writing to the file at the same time, thus avoiding the race situation 🙂
  4. Close the file when you’re done.

Let’s start by writing the produce function, which generates random numbers.

func produce(data chan int, wg *sync.WaitGroup) {  
    n := rand.Intn(999)
    data <- n
    wg.Done()
}
Copy the code

The above function generates a random number and writes it to the channel data, then calls Done on the wait group to notify it that it has completed its task.

Let’s move on to the function that now writes to the file.

func consume(data chan int, done chan bool) {  
    f, err := os.Create("concurrent")
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    for d := range data {
        _, err = fmt.Fprintln(f, d)
        iferr ! =nil {
            fmt.Println(err)
            f.Close()
            done <- false
            return
        }
    }
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        done <- false
        return
    }
    done <- true
}
Copy the code

The consume function creates a file named Concurrent. It then reads the random number from the data channel and writes it to the file. Once all the random numbers have been read and written, true is written to the completed channel to inform it that it has completed its task.

Let’s write the main function to complete the program. I’ve provided the entire program below.

package main

import (  
    "fmt"
    "math/rand"
    "os"
    "sync"
)

func produce(data chan int, wg *sync.WaitGroup) {  
    n := rand.Intn(999)
    data <- n
    wg.Done()
}

func consume(data chan int, done chan bool) {  
    f, err := os.Create("concurrent")
    iferr ! =nil {
        fmt.Println(err)
        return
    }
    for d := range data {
        _, err = fmt.Fprintln(f, d)
        iferr ! =nil {
            fmt.Println(err)
            f.Close()
            done <- false
            return
        }
    }
    err = f.Close()
    iferr ! =nil {
        fmt.Println(err)
        done <- false
        return
    }
    done <- true
}

func main(a) {  
    data := make(chan int)
    done := make(chan bool)
    wg := sync.WaitGroup{}
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go produce(data, &wg)
    }
    go consume(data, done)
    go func(a) {
        wg.Wait()
        close(data)
    }()
    d := <-done
    if d == true {
        fmt.Println("File written successfully")}else {
        fmt.Println("File writing failed")}}Copy the code

The main function creates a data channel from which random numbers are read and written. Done’s channel consumption Goroutine notifies Main that it has completed its task. Wg’s WaitGroup is used to wait for all 100 goroutines to finish generating random numbers.

The for loop creates 100 and goroutines. The goroutine calls wait () on the wait group to wait for all 100 Goroutines to finish creating random numbers. After that, it closes the channel. Once the channel is closed, and the consuming Goroutine has written all the generated random numbers to the file, it writes true to the done channel. The main goroutine unblocks and prints File written successfully.

Now you can open the file in any text editor at the same time and see 100 generated random numbers 🙂

This brings us to the end of the tutorial. Hope you enjoy reading. Have a nice day.