Environment Variables
Getenv ยท Setenv ยท LookupEnvUse
os.LookupEnv instead of os.Getenv when you need to distinguish between a variable that is unset vs. one that is set to an empty string.
Getenv, LookupEnv, Setenv, Unsetenv
Env
// Getenv โ empty string if not set (can't distinguish unset vs "") host := os.Getenv("DB_HOST") // LookupEnv โ second return tells you if the key exists port, ok := os.LookupEnv("DB_PORT") if !ok { port = "5432" // use default } // Setenv / Unsetenv os.Setenv("APP_ENV", "production") os.Unsetenv("APP_ENV") // Environ โ all env vars as "KEY=VALUE" strings for _, e := range os.Environ() { fmt.Println(e) // PATH=/usr/bin:..., HOME=/Users/alice, ... } // Clearenv โ remove all environment variables os.Clearenv()
Process Info
Args ยท Getpid ยท Exit ยท Stdin
Args and process identity
Process
// os.Args โ command-line arguments // Args[0] is the program name fmt.Println(os.Args[0]) // ./myapp fmt.Println(os.Args[1:]) // remaining args os.Getpid() // current process ID os.Getppid() // parent process ID os.Getuid() // numeric user ID os.Getgid() // numeric group ID hostname, _ := os.Hostname() wd, _ := os.Getwd() // working directory
Stdin, Stdout, Stderr and Exit
Streams
// Standard streams are *os.File values fmt.Fprintln(os.Stdout, "to stdout") fmt.Fprintln(os.Stderr, "error output") // Read a line from stdin scanner := bufio.NewScanner(os.Stdin) if scanner.Scan() { line := scanner.Text() fmt.Println("got:", line) } // Exit โ immediately terminates the process // defer statements do NOT run before os.Exit os.Exit(0) // success os.Exit(1) // failure
Reading & Writing Files
ReadFile ยท WriteFile ยท Open ยท Createos.ReadFile and os.WriteFile are convenience wrappers that handle open/read/close in one call. Use os.Open / os.Create when you need streaming, seeking, or finer control.
ReadFile โ read entire file at once
ReadFile
// ReadFile reads and closes in one call data, err := os.ReadFile("config.json") if err != nil { log.Fatal(err) } fmt.Println(string(data)) // Combine with JSON decode var cfg Config data, _ = os.ReadFile("config.json") json.Unmarshal(data, &cfg)
WriteFile โ write bytes to a file
WriteFile
// WriteFile creates or truncates, then writes content := []byte("Hello, World!\n") err := os.WriteFile("output.txt", content, 0644) // Common pattern: marshal then write data, _ := json.MarshalIndent(cfg, "", " ") os.WriteFile("config.json", data, 0644) // File permissions (Unix octal) // 0644 โ owner rw, group r, others r (files) // 0755 โ owner rwx, group rx, others rx (dirs/executables)
Open and Create โ streaming file access
Open / Create
// Open โ read-only f, err := os.Open("data.txt") if err != nil { log.Fatal(err) } defer f.Close() // use f as an io.Reader (bufio.Scanner, json.Decoder, etc.) // Create โ create or truncate for writing out, err := os.Create("output.txt") if err != nil { log.Fatal(err) } defer out.Close() fmt.Fprintln(out, "line 1") fmt.Fprintln(out, "line 2") // OpenFile โ full control over flags and permissions f2, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) defer f2.Close() fmt.Fprintln(f2, "appended line")
OpenFile flags reference
Flags
os.O_RDONLY // read-only (default for Open) os.O_WRONLY // write-only os.O_RDWR // read+write os.O_APPEND // append on each write os.O_CREATE // create if not exists os.O_EXCL // error if file exists (with O_CREATE) os.O_TRUNC // truncate to zero on open os.O_SYNC // synchronous I/O // Combine with bitwise OR // Read+write, create if absent, don't truncate: flags := os.O_RDWR | os.O_CREATE
File System Operations
Stat ยท Mkdir ยท Remove ยท Rename
Stat โ inspect a file or directory
Stat
info, err := os.Stat("data.txt") if err != nil { if os.IsNotExist(err) { fmt.Println("file does not exist") } } info.Name() // "data.txt" info.Size() // 1024 (bytes) info.Mode() // -rw-r--r-- (FileMode) info.ModTime() // time.Time info.IsDir() // false // Lstat โ like Stat but doesn't follow symlinks info2, _ := os.Lstat("link.txt")
Mkdir, MkdirAll, Remove, RemoveAll
Dirs
// Mkdir โ create one directory (parent must exist) os.Mkdir("logs", 0755) // MkdirAll โ create full path, like mkdir -p os.MkdirAll("data/2024/reports", 0755) // Remove โ delete a file or empty directory os.Remove("temp.txt") // RemoveAll โ delete a path and all its contents os.RemoveAll("data/cache") // Rename โ move or rename os.Rename("old.txt", "new.txt") os.Rename("file.txt", "archive/file.txt")
ReadDir โ list directory contents
ReadDir
// ReadDir returns entries sorted by name entries, err := os.ReadDir(".") if err != nil { log.Fatal(err) } for _, e := range entries { fmt.Printf("%s dir=%v\n", e.Name(), e.IsDir()) } // Get full FileInfo if needed for _, e := range entries { info, _ := e.Info() fmt.Printf("%-20s %6d bytes\n", e.Name(), info.Size()) } // Temp files and directories f, _ := os.CreateTemp("", "prefix-*.txt") defer os.Remove(f.Name()) dir, _ := os.MkdirTemp("", "workdir-*") defer os.RemoveAll(dir)
Error Checking
IsNotExist ยท IsExist ยท IsPermissionPrefer
errors.Is(err, fs.ErrNotExist) over os.IsNotExist(err) for wrapped errors. The os.Is* helpers work on the raw error only.
Checking specific OS error types
Errors
import ( "errors" "io/fs" ) _, err := os.Open("missing.txt") // Modern style โ works through wrapped errors errors.Is(err, fs.ErrNotExist) // true errors.Is(err, fs.ErrPermission) // false errors.Is(err, fs.ErrExist) // false // Legacy helpers (don't unwrap) os.IsNotExist(err) // true os.IsExist(err) // true when creating an already-existing file os.IsPermission(err) // true for EACCES / EPERM os.IsTimeout(err) // true for timeout errors // Extract the underlying *PathError for details var pe *os.PathError if errors.As(err, &pe) { fmt.Println(pe.Op, pe.Path, pe.Err) // open missing.txt no such file or directory }
Running Commands โ os/exec
Command ยท Output ยท Run ยท StdinNever construct shell commands by concatenating user input โ that's a command injection vulnerability. Pass arguments as separate strings to
exec.Command and they're never interpreted by a shell.
exec.Command โ capture output
Output
import "os/exec" // Output โ run and capture stdout; returns error if exit code != 0 out, err := exec.Command("git", "rev-parse", "HEAD").Output() if err != nil { log.Fatal(err) } fmt.Println(strings.TrimSpace(string(out))) // CombinedOutput โ capture stdout + stderr together out2, err := exec.Command("go", "build", "./...").CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "build failed:\n%s\n", out2) } // Run โ just run, no output capture err = exec.Command("go", "fmt", "./...").Run()
Cmd struct โ full control over streams and env
Cmd
cmd := exec.Command("ffmpeg", "-i", "input.mp4", "output.mp3") // Pipe stdout/stderr to our own writers cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr // Provide stdin cmd.Stdin = strings.NewReader("input data") // Set working directory cmd.Dir = "/tmp/work" // Override or extend environment cmd.Env = append(os.Environ(), "GOFLAGS=-mod=vendor") if err := cmd.Run(); err != nil { var exitErr *exec.ExitError if errors.As(err, &exitErr) { fmt.Println("exit code:", exitErr.ExitCode()) } }
Start + Wait โ async execution
Async
// Start begins the command; Wait blocks until done cmd := exec.Command("sleep", "5") if err := cmd.Start(); err != nil { log.Fatal(err) } fmt.Println("pid:", cmd.Process.Pid) // do other work here ... if err := cmd.Wait(); err != nil { log.Fatal(err) }
LookPath โ find a binary
LookPath
// LookPath resolves a binary name to a full path path, err := exec.LookPath("git") if err != nil { log.Fatal("git not found") } fmt.Println(path) // /usr/bin/git // Check availability without running _, err = exec.LookPath("docker") dockerAvailable := err == nil
Quick Reference
All key functions| Function | Returns | Description |
|---|---|---|
| os.Getenv(key) | string | Value of env var; empty if unset |
| os.LookupEnv(key) | string, bool | Value and whether the key exists |
| os.Setenv(key, val) | error | Set an environment variable |
| os.Unsetenv(key) | error | Delete an environment variable |
| os.Environ() | []string | All env vars as "KEY=VALUE" |
| os.Args | []string | Command-line arguments; [0] is program name |
| os.Getpid() | int | Current process ID |
| os.Getwd() | string, error | Current working directory |
| os.Hostname() | string, error | Machine hostname |
| os.Exit(code) | โ | Terminate process; defers do NOT run |
| os.ReadFile(name) | []byte, error | Read entire file |
| os.WriteFile(name, data, perm) | error | Write/overwrite entire file |
| os.Open(name) | *File, error | Open file for reading |
| os.Create(name) | *File, error | Create or truncate for writing |
| os.OpenFile(name, flag, perm) | *File, error | Open with custom flags |
| os.Stat(name) | FileInfo, error | File metadata (size, mode, modtime) |
| os.Lstat(name) | FileInfo, error | Like Stat but doesn't follow symlinks |
| os.Mkdir(name, perm) | error | Create a single directory |
| os.MkdirAll(path, perm) | error | Create full directory path (mkdir -p) |
| os.Remove(name) | error | Delete file or empty directory |
| os.RemoveAll(path) | error | Delete path and all contents |
| os.Rename(old, new) | error | Move or rename a file |
| os.ReadDir(name) | []DirEntry, error | List directory contents, sorted |
| os.CreateTemp(dir, pattern) | *File, error | Create a unique temp file |
| os.MkdirTemp(dir, pattern) | string, error | Create a unique temp directory |
| os.IsNotExist(err) | bool | True if error is "file not found" |
| os.IsPermission(err) | bool | True if error is permission denied |
| Function (os/exec) | Returns | Description |
|---|---|---|
| exec.Command(name, args...) | *Cmd | Create a Cmd; does not start it |
| cmd.Output() | []byte, error | Run and capture stdout |
| cmd.CombinedOutput() | []byte, error | Run and capture stdout + stderr |
| cmd.Run() | error | Run and wait; no output capture |
| cmd.Start() | error | Start without waiting |
| cmd.Wait() | error | Wait for a started command to finish |
| exec.LookPath(file) | string, error | Find binary in PATH |