Golang的os包是标准库中负责操作系统交互的核心包,其中包含了大量用于文件、目录操作的API,能够覆盖绝大多数本地文件处理的场景,不需要引入第三方依赖即可完成常规的文件操作任务。

os包文件操作的核心基础
在使用os包操作文件前,需要先了解几个核心的概念和通用规则。所有文件操作的方法返回值中,第一个通常是操作结果或者文件对象,第二个是error类型,操作时一定要处理错误,避免程序出现不可预期的问题。文件操作完成后,需要调用文件对象的Close方法释放资源,推荐使用defer关键字确保操作完成后自动关闭。
文件打开与创建
打开文件可以使用os.Open方法,该方法默认以只读模式打开文件,如果文件不存在会返回错误。如果需要创建文件或者指定打开模式,可以使用os.OpenFile方法,该方法支持自定义打开标志和文件权限。
package main
import (
"fmt"
"os"
)
func main() {
// 只读模式打开文件,文件不存在会报错
file1, err := os.Open("test.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file1.Close()
// 创建文件,如果文件存在则清空内容,权限为0644,即所有者可读写,其他用户只读
file2, err := os.OpenFile("new_test.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
defer file2.Close()
fmt.Println("文件创建成功")
}
文件写入操作
文件对象提供了Write和WriteString方法用于写入数据,也可以使用io包的WriteString方法配合文件对象完成写入。如果需要追加内容到文件,只需要在OpenFile的标志中加入os.O_APPEND即可。
package main
import (
"fmt"
"os"
)
func main() {
// 以追加模式打开文件,不存在则创建
file, err := os.OpenFile("write_test.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
// 写入字符串
n, err := file.WriteString("这是第一行写入的内容n")
if err != nil {
fmt.Println("写入失败:", err)
return
}
fmt.Printf("成功写入%d字节n", n)
// 写入字节切片
data := []byte("这是第二行写入的内容n")
n, err = file.Write(data)
if err != nil {
fmt.Println("写入失败:", err)
return
}
fmt.Printf("成功写入%d字节n", n)
}
文件读取操作
读取文件可以使用文件对象的Read方法,该方法需要传入字节切片作为缓冲区,返回读取的字节数和可能的错误。如果需要一次性读取整个文件,也可以使用os包的ReadFile方法,该方法会直接返回文件的全部内容。
package main
import (
"fmt"
"os"
)
func main() {
// 方式1:使用ReadFile一次性读取整个文件
content, err := os.ReadFile("write_test.txt")
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Println("文件全部内容:")
fmt.Println(string(content))
// 方式2:使用Read方法分批次读取
file, err := os.Open("write_test.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
buf := make([]byte, 1024) // 1KB缓冲区
fmt.Println("分批次读取内容:")
for {
n, err := file.Read(buf)
if n > 0 {
fmt.Print(string(buf[:n]))
}
if err != nil {
break
}
}
}
文件删除与重命名
os包提供了Remove方法用于删除单个文件或者空目录,如果需要删除非空目录,可以使用RemoveAll方法。重命名文件或者移动文件可以使用Rename方法,该方法在不同操作系统上都可以正常工作。
package main
import (
"fmt"
"os"
)
func main() {
// 重命名文件
err := os.Rename("new_test.txt", "rename_test.txt")
if err != nil {
fmt.Println("重命名失败:", err)
return
}
fmt.Println("重命名成功")
// 删除文件
err = os.Remove("rename_test.txt")
if err != nil {
fmt.Println("删除文件失败:", err)
return
}
fmt.Println("删除文件成功")
// 删除非空目录
err = os.RemoveAll("test_dir")
if err != nil {
fmt.Println("删除目录失败:", err)
return
}
fmt.Println("删除目录成功")
}
目录相关操作
目录创建与遍历
创建单个目录可以使用Mkdir方法,需要指定目录权限,如果父目录不存在会返回错误。如果需要创建多级目录,可以使用MkdirAll方法。遍历目录可以使用ReadDir方法,该方法会返回目录下的所有文件和子目录信息。
package main
import (
"fmt"
"os"
)
func main() {
// 创建多级目录
err := os.MkdirAll("a/b/c", 0755)
if err != nil {
fmt.Println("创建目录失败:", err)
return
}
fmt.Println("多级目录创建成功")
// 遍历目录
entries, err := os.ReadDir("a")
if err != nil {
fmt.Println("遍历目录失败:", err)
return
}
fmt.Println("a目录下的内容:")
for _, entry := range entries {
if entry.IsDir() {
fmt.Printf("目录: %sn", entry.Name())
} else {
fmt.Printf("文件: %sn", entry.Name())
}
}
}
获取文件信息
如果需要获取文件或者目录的元信息,比如大小、修改时间、是否为目录等,可以使用os.Stat方法,该方法返回os.FileInfo接口,包含了所有元信息。
package main
import (
"fmt"
"os"
"time"
)
func main() {
info, err := os.Stat("write_test.txt")
if err != nil {
fmt.Println("获取文件信息失败:", err)
return
}
fmt.Printf("文件名: %sn", info.Name())
fmt.Printf("文件大小: %d字节n", info.Size())
fmt.Printf("是否为目录: %vn", info.IsDir())
fmt.Printf("修改时间: %sn", info.ModTime().Format(time.RFC3339))
fmt.Printf("文件权限: %sn", info.Mode().String())
}
操作注意事项
- 所有文件操作都需要处理错误,避免忽略error导致程序异常
- 打开的文件一定要关闭,推荐使用defer语句确保关闭操作执行
- 文件权限参数在Windows系统上部分场景不生效,属于正常现象
- 操作文件前可以先使用os.Stat判断文件是否存在,避免不必要的错误
- 大文件读取不建议使用ReadFile一次性读取,避免占用过多内存