File Input/Output is an essential subject in almost every Programming languages. Fortunately, it’s not hard to deal with I/O in Go.

Read File

To Open a file in Go, use the Open function from the os package.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("test.txt")
    if (err != nil) {
        return
    }
    // Close the file immediately after finishing
    defer file.Close()

    fileStat, err := file.Stat()
    if (err != nil) {
        return
    }
    fileSize := stat.Size()

    // Make a buffer with the same size with file, in order to store file's content
    buffer := make([]byte, fileSize)

    // Read file's content into 
    _, err = file.Read(buffer)
    if(err != nil) {
        return
    }

    // Convert buffer into string
    str := string(bufferString)
    fmt.Println(str)
}

Actually, there’s a simpler way to read from a file, without having to close it, using the io/ioutil package

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    buffer, err := ioutil.ReadFile("test.txt")
    if (err != nil) {
        return
    }
    str := string(buffer)
    fmt.Println(str)
}

You can see that we could read file’s content with just a few number lines of code.

Create File

We can use os.Create function to create a file with Go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Create("new_file.txt")
    if (err != nil) {
        return
    }

    // Close the file immediately after finishing
    defer file.Close()

    file.WriteString("Hello, world")
    
}

After running this programming, a file named “new_file.txt” will be generated.

Get the content of directories

Instead of reading from a file, we can use os.Read to get the content of a directory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
    "fmt"
    "os"
)

func main() {
    dir, err := os.Read(".")
    if (err != nil) {
        return
    }

    // Close the directory immediately after finishing
    defer dir.Close()

    // Get info of the files in current directory
    fileInfos, err := dir.Readdir(-1)
    if (err != nil) {
        return
    }

    // Print out the files name
    for _, fileInfo := range fileInfos {
        fmt.Println(fileInfo.Name())
    }
    
}

The dir.Readdir(int) function return info of the files in current directory, and error if occurred. Pass an argument to specify how many files would be read. You can just pass -1 to get info of every files in the directory.

Walk through a directory

Sometimes, we want to recursively walk a folder (read the folder’s contents, all the subfolders, all the sub-subfolders, etc.). We can use the Walk function provided in the path/filepath package:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
    "fmt"
    "path/filepath"
    "os"
)

func walkCallback(path string, info os.FileInfo, err error) error {
    fmt.Println(path)
    return nil
}

func main() {
    filepath.walk(".", walkCallback)
}