os 包常用函数速查
os 是 Go 标准库中与操作系统打交道的核心包:环境变量、文件 I/O、进程、命令行参数、信号 都在这里。
核心分类(先记这个,函数全会)
| 分类 | 关键词 | 代表函数 |
|---|---|---|
| 环境变量 | Env | Getenv / Setenv / LookupEnv |
| 命令行 | Args | os.Args |
| 文件读写 | File | Open / Create / ReadFile / WriteFile |
| 文件信息 | Stat | Stat / IsNotExist |
| 目录 | Dir/Mkdir | Mkdir / MkdirAll / ReadDir |
| 删除重命名 | Remove | Remove / RemoveAll / Rename |
| 进程 | Exit | Exit / Getpid / Getwd |
| 标准流 | Std | os.Stdin / os.Stdout / os.Stderr |
环境变量 ⭐ 最常用
go
host := os.Getenv("REDIS_HOST") // 不存在返回 ""
os.Setenv("ENV", "dev")
v, ok := os.LookupEnv("REDIS_PORT") // 区分 "未设置" 和 "空字符串"
if !ok { /* 没设置 */ }
os.Unsetenv("FOO") // 删除(注销)当前进程中名为 FOO 的环境变量。
all := os.Environ() // []string,每项 "KEY=VAL" 例如 ["PATH=/usr/bin", "USER=root", "HOME=/root"])。
命令行参数
go
// os.Args[0] 是程序名,后面才是参数
fmt.Println(os.Args) // ["./app", "-port=8080", "dev"]
if len(os.Args) > 1 {
mode := os.Args[1]
}
复杂参数用 flag 包,不要手写解析。
文件读写(小文件,一行搞定)⭐
go
// 读整个文件
data, err := os.ReadFile("config.yaml") // []byte
// 写整个文件(覆盖)
err := os.WriteFile("out.txt", []byte("hi"), 0644)
权限位 0644:所有者读写,其他人只读。常用值:
0644普通文件0755可执行文件 / 目录0600私密文件(仅所有者)
文件读写(大文件 / 流式)
go
// 只读打开
f, err := os.Open("big.log")
defer f.Close()
// 创建(已存在则截断为空)
f, err := os.Create("out.txt")
defer f.Close()
// 自定义模式(追加、读写等)
f, err := os.OpenFile("log.txt",
os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
*os.File 同时实现 io.Reader / io.Writer,可直接传给 bufio.NewScanner、fmt.Fprintf、io.Copy 等。
OpenFile 标志位(按需组合)
| 标志 | 含义 |
|---|---|
O_RDONLY |
只读 |
O_WRONLY |
只写 |
O_RDWR |
读写 |
O_CREATE |
不存在则创建 |
O_APPEND |
追加写入 |
O_TRUNC |
打开时清空 |
O_EXCL |
与 O_CREATE 一起:已存在则报错 |
文件信息 / 判断存在
go
info, err := os.Stat("config.yaml")
if os.IsNotExist(err) {
// 文件不存在
}
info.Name() // 文件名
info.Size() // 字节数
info.Mode() // 权限
info.ModTime() // 修改时间
info.IsDir() // 是否目录
目录操作
go
os.Mkdir("data", 0755) // 只建一层,父目录不存在会报错
os.MkdirAll("a/b/c", 0755) // 递归创建,常用 ⭐
entries, _ := os.ReadDir("./logs") // []os.DirEntry
for _, e := range entries {
fmt.Println(e.Name(), e.IsDir())
}
dir, _ := os.Getwd() // 当前工作目录
os.Chdir("/tmp") // 切换工作目录
tmp := os.TempDir() // 系统临时目录(/tmp 或 C:\Users\xxx\AppData\Local\Temp)
home, _ := os.UserHomeDir() // 用户家目录
删除 / 重命名
go
os.Remove("foo.txt") // 只删文件或空目录
os.RemoveAll("./tmp") // 递归删除(危险!等同 rm -rf)
os.Rename("old.txt", "new.txt")
标准流
go
fmt.Fprintln(os.Stdout, "正常输出")
fmt.Fprintln(os.Stderr, "错误输出") // 错误日志一律走 Stderr
// 从标准输入读
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
}
os.Stdin / Stdout / Stderr 都是 *os.File,能传给所有接收 io.Writer/io.Reader 的函数。
进程控制
go
os.Exit(0) // 立即退出,defer 不会执行 ⚠️
os.Exit(1) // 非 0 表示错误,CI/Shell 会感知
os.Getpid() // 当前进程 PID
os.Getppid() // 父进程 PID
os.Hostname() // 主机名
log.Fatal内部就是Exit(1);想让 defer 生效,应return或panic,别用Exit。
临时文件 / 目录
go
f, _ := os.CreateTemp("", "upload-*.tmp") // 自动唯一文件名
defer os.Remove(f.Name())
dir, _ := os.MkdirTemp("", "build-*")
defer os.RemoveAll(dir)
* 会被替换成随机字符串,传 "" 表示用系统临时目录。
实战速记
go
// 读环境变量(带兜底)
port := os.Getenv("PORT")
if port == "" { port = "8080" }
// 判断文件是否存在
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
// 不存在
}
// 追加写日志
f, _ := os.OpenFile("app.log",
os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
defer f.Close()
fmt.Fprintf(f, "%s %s\n", time.Now().Format(time.RFC3339), msg)
// 出错就退出
if err != nil {
fmt.Fprintln(os.Stderr, "fatal:", err)
os.Exit(1)
}
一句话记忆
Getenv读环境,ReadFile/WriteFile一把梭小文件,Open/Create/OpenFile处理大文件流;
Stat + IsNotExist判存在,MkdirAll + RemoveAll管目录;
Stdin/Stdout/Stderr是*os.File,Exit不走 defer。