Working with Go
Working with Files
Reading File
You can read a complete file in using os.ReadFile
. See ReadFile documentation The function returns two variables, the first the content of the file. The second variable is the error if one occurred. If no error, than err
will be nil
filename := "./extras/rabbits.txt"
content, err := os.ReadFile(filename)
if err != nil {
log.Fatalln("Error reading file", filename)
}
The content is returned as a []byte
and not a string. You need to cast to a string to use as such, for example to display. Use string()
to cast a []byte
to string
type.
fmt.Println(string(content))
Check if File Exists
One of the above errors can be if the file does not exist. You can use os.Stat
to check explicitly if file exists without trying to open.
if _, err := os.Stat("junk.foo"); os.IsNotExist(err) {
fmt.Println(">>>")
fmt.Println("File: junk.foo does not exist")
}
Read File Line-by-Line
One way to process a file line by line, would be to read the entire file in, like the first example above, and then split on the line ending.
lines = strings.Split( string(content), "\n" )
The above is perfectly fine and works for most files. If you have a large file, for example one that can not be stored in memory, you can use the bufio
package. See bufio package documentaiton.
Here is a way to process a large file line-by-line in golang.
file, err := os.Open(filename)
if err != nil {
fmt.Println("Error opening file: ", err)
}
defer file.Close() // see explanation below
// Use bufio scanner, the default Scan method is by line
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
The defer
statement defers the execution until the surrounding function (or overall program) completes. You should always use defer
for something that needs to be closed, or cleaned up.
Write to a new File
Use os.WriteFile
to write a file out. The function takes three variables, the filename, the content (as a []byte
) and the file system mode.
outfile := "output.txt"
err = os.WriteFile(outfile, content, 0644)
if err != nil {
fmt.Println("Error writing file: ", err)
} else {
fmt.Println(">>>")
fmt.Println("Created: ", outfile)
}
Append to an existing File
You can write out to an existing file appending the content using the following.
af, err := os.OpenFile(outfile, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("Error appending to file:", err)
}
defer af.Close()
if _, err = af.WriteString("Appending this text"); err != nil {
fmt.Println("Error writing to file:", err)
}
Using Filepath
Use the filepath
package for working with cross-platform paths properly. See filepath package documentaiton. For example, use filepath.Join
for creating a path with directory.
package main
import (
"fmt"
"path/filepath"
)
func main() {
fmt.Println(filepath.Join("a", "b", "file.ext"))
}
See filepath package documentation for additional function, including splitting paths, checking filename extension, base and more.