The standard library os package is what people mean by searches like golang os or os golang: paths on disk, golang os open style reads, os create golang with os.Create, os writefile golang with os.WriteFile, and streaming I/O through *os.File. This article sticks to that golang file API; for more read patterns, see ways to read a file in Go.
Tested with Go 1.24 on Linux.
golang os package and *os.File
os exposes functions such as Open, Create, OpenFile, ReadFile, WriteFile, Stat, Remove, and Rename. Successful open or create calls return a concrete *os.File, which implements io.Reader, io.Writer, io.Closer, and related interfaces, so helpers that take those interfaces accept a *os.File after you open or create it.
golang os open (os.Open, os.OpenFile)
os.Open opens a path read-only and matches the usual os open golang flow when you only need to read bytes or scan lines. os.OpenFile is the general form: you pass flags such as os.O_RDONLY, os.O_WRONLY, os.O_RDWR, plus os.O_CREATE, os.O_APPEND, and os.O_TRUNC as needed, and a FileMode used when new files are created (subject to the process umask on Unix).
Always check the error before using the file, then defer Close on the non-nil *os.File:
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
f, err := os.Open("notes.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
sc := bufio.NewScanner(f)
for sc.Scan() {
fmt.Println(sc.Text())
}
if err := sc.Err(); err != nil {
log.Fatal(err)
}
}Run it from a directory that contains notes.txt; each line prints once. For whole small files, os.ReadFile avoids managing a Close yourself:
package main
import (
"fmt"
"log"
"os"
)
func main() {
b, err := os.ReadFile("notes.txt")
if err != nil {
log.Fatal(err)
}
fmt.Print(string(b))
}os create golang (os.Create)
os.Create creates or truncates the named file and opens it read-write. Typical os create golang code then writes through the returned *os.File. Do not defer Close until you know err is nil:
package main
import (
"fmt"
"log"
"os"
)
func main() {
f, err := os.Create("demo.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
if _, err := f.WriteString("hello\n"); err != nil {
log.Fatal(err)
}
fmt.Println("created and wrote")
}created and wrotedemo.txt then contains hello on its own line.
os writefile golang and appending (os.WriteFile, OpenFile)
os.WriteFile is the usual os writefile golang choice when you have a []byte (or a string converted to bytes) and want create-or-truncate behavior in one call:
package main
import (
"log"
"os"
)
func main() {
if err := os.WriteFile("out.txt", []byte("first\n"), 0o644); err != nil {
log.Fatal(err)
}
}To append without truncating, open with os.O_APPEND|os.O_CREATE|os.O_WRONLY:
package main
import (
"log"
"os"
)
func main() {
f, err := os.OpenFile("out.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
log.Fatal(err)
}
if _, err := f.WriteString("second\n"); err != nil {
f.Close()
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}After both snippets, out.txt contains two lines (first then second). Pick 0o644 or tighter modes for real services; the effective mode still respects umask on Unix.
Stat, remove, and “file exists”
os.Stat returns fs.FileInfo (size, mod time, mode, directory bit). Combine it with errors.Is and os.ErrNotExist instead of parsing error strings; wording for golang file errors differs across operating systems. The snippet below assumes out.txt already exists from the os.WriteFile / append examples in the same working directory.
package main
import (
"errors"
"fmt"
"os"
"time"
)
func main() {
if _, err := os.Stat("missing.txt"); err != nil {
fmt.Println("missing:", errors.Is(err, os.ErrNotExist))
}
fi, err := os.Stat("out.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("size=%d mod=%s\n", fi.Size(), fi.ModTime().UTC().Format(time.RFC3339))
}os.Remove deletes a file; a missing path returns an error whose message depends on the platform:
remove gone.txt: no such file or directorySummary
The golang os package centers on paths and *os.File handles. Golang os open style code uses os.Open for read-only work or os.OpenFile when you need create, append, or read-write combinations. The os create golang pattern maps to os.Create, which truncates existing paths. The os writefile golang pattern maps to os.WriteFile for small one-shot writes, while append and mixed modes stay on OpenFile. Check errors before defer Close, use errors.Is(err, os.ErrNotExist) after Stat, and choose ReadFile or a scanner depending on file size.

