一、文件操作(File I/O)
1. 基础文件操作
函数/方法 | 作用描述 |
os.Create(filename) | 创建文件(覆盖已存在文件),返回 *os.File |
os.Open(filename) | 以只读模式打开文件 |
os.OpenFile(name, flag, perm) | 高级打开方式(指定标志和权限) |
file.Read(b []byte) | 读取文件内容到字节数组 |
file.Write(b []byte) | 写入字节数组到文件 |
file.Close() | 关闭文件(必须显式调用,避免资源泄漏) |
os.Remove(filename) | 删除文件 |
文件打开模式(常用组合):
os.O_RDONLY // 只读
os.O_WRONLY // 只写
os.O_CREATE // 不存在则创建
os.O_APPEND // 追加模式
os.O_TRUNC // 打开时清空文件
os.O_EXCL // 与O_CREATE配合,文件必须不存在
示例代码:
// 创建并写入文件
file, err := os.Create("data.txt")
if err != nil {
panic(err)
}
defer file.Close()
file.WriteString("Hello, OS Package!\n")
// 读取文件内容
content, err := os.ReadFile("data.txt") // 快捷方法(Go 1.16+)
if err == nil {
fmt.Println(string(content)) // "Hello, OS Package!"
}
二、目录操作(Directory)
1. 目录管理方法
函数 | 作用描述 |
os.Mkdir(name, perm) | 创建单级目录(权限如0755) |
os.MkdirAll(path, perm) | 递归创建多级目录 |
os.ReadDir(dirname) | 读取目录内容(返回[]DirEntry) |
os.Remove(dirname) | 删除空目录 |
os.RemoveAll(path) | 递归删除目录及其内容 |
os.Rename(oldpath, newpath) | 重命名/移动文件或目录 |
示例代码:
// 递归创建目录
if err := os.MkdirAll("project/logs/2023", 0755); err != nil {
log.Fatal(err)
}
// 遍历目录
entries, _ := os.ReadDir("project")
for _, entry := range entries {
fmt.Println(entry.Name(), entry.IsDir())
}
// 删除整个目录树
os.RemoveAll("project")
三、环境变量管理(Environment Variables)
1. 核心方法
函数 | 作用描述 |
os.Setenv(key, value) | 设置环境变量 |
os.Getenv(key) | 获取环境变量(不存在返回空字符串) |
os.LookupEnv(key) | 返回变量值和是否存在标志 |
os.Unsetenv(key) | 删除环境变量 |
os.Environ() | 获取所有环境变量(KEY=value格式) |
示例代码:
// 设置并获取环境变量
os.Setenv("API_KEY", "secret123")
key := os.Getenv("API_KEY")
// 安全获取变量
if dbURL, ok := os.LookupEnv("DB_URL"); ok {
fmt.Println("Database URL:", dbURL)
} else {
fmt.Println("DB_URL not set")
}
// 打印所有环境变量
for _, env := range os.Environ() {
fmt.Println(env)
}
四、进阶技巧与性能优化
1. 高效文件读写
- 分块读取大文件(避免内存溢出):
file, _ := os.Open("large.log")
defer file.Close()
buffer := make([]byte, 4096) // 4KB缓冲区
for {
n, err := file.Read(buffer)
if err == io.EOF {
break
}
process(buffer[:n])
}
- 缓冲写入(提升I/O性能):
file, _ := os.Create("output.log")
writer := bufio.NewWriter(file)
defer func() {
writer.Flush() // 确保缓冲区数据写入磁盘
file.Close()
}()
writer.WriteString("Buffered write\n")
2. 文件信息与权限
// 获取文件元数据
info, _ := os.Stat("data.txt")
fmt.Println("Size:", info.Size(), "ModTime:", info.ModTime())
// 修改文件权限
os.Chmod("script.sh", 0755) // rwxr-xr-x
os.Chown("data.txt", 1000, 1000) // 设置UID/GID(需权限)
五、常见错误与最佳实践
1. 典型陷阱
- 资源泄漏:忘记调用file.Close()或未使用defer
// 错误:未关闭文件
file, _ := os.Open("data.txt")
// 正确:使用defer
file, _ := os.Open("data.txt")
defer file.Close()
- 路径分隔符硬编码:
// 错误(Windows不兼容)
path := "data\\file.txt"
// 正确:使用filepath包
path := filepath.Join("data", "file.txt")
2. 安全实践
- 检查文件是否存在:
if _, err := os.Stat("config.yaml"); errors.Is(err, os.ErrNotExist) {
// 文件不存在时的处理
}
- 原子写入(避免写入过程中崩溃导致数据损坏):
tmpFile := "data.tmp"
finalFile := "data.txt"
os.WriteFile(tmpFile, data, 0644)
os.Rename(tmpFile, finalFile) // 原子操作
六、实战示例:配置文件加载器
package main
import (
"fmt"
"os"
"path/filepath"
)
func LoadConfig() {
// 优先从环境变量获取配置路径
configPath := os.Getenv("CONFIG_PATH")
if configPath == "" {
configPath = filepath.Join("etc", "app", "config.yaml")
}
// 检查文件是否存在
if _, err := os.Stat(configPath); err != nil {
panic("Config file not found: " + configPath)
}
// 读取配置内容
data, err := os.ReadFile(configPath)
if err != nil {
panic(err)
}
fmt.Printf("Loaded config: \n%s\n", data)
}
func main() {
os.Setenv("CONFIG_PATH", "custom_config.yaml")
LoadConfig()
}
七、跨平台注意事项
- 路径处理:始终使用filepath.Join()代替手动拼接/或\
- 行尾符:\n在Windows中会自动转换为\r\n
- 权限位:Windows忽略部分Unix权限标志(如可执行位)
通过掌握 os 包的核心功能,可实现对系统资源的精细控制。建议结合具体场景练习:
- 实现日志轮转工具(按日期分割文件)
- 开发CLI工具处理目录批量重命名
- 编写配置管理模块(环境变量+文件优先级)