Go 语言提供了强大且简洁的文件操作功能,主要通过 os、io 和 bufio 等标准库实现。下面我将详细介绍 Go 中的各种文件操作方法。
1. 基本文件操作
创建文件
package main
import (
"fmt"
"os"
)
func main() {
// 创建文件
file, err := os.Create("test.txt")
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
defer file.Close()
fmt.Println("文件创建成功")
}
打开文件
// 以只读方式打开
file, err := os.Open("test.txt")
// 以读写方式打开
file, err := os.OpenFile("test.txt", os.O_RDWR, 0644)
// 常用打开模式:
// os.O_RDONLY: 只读
// os.O_WRONLY: 只写
// os.O_RDWR: 读写
// os.O_APPEND: 追加
// os.O_CREATE: 如果不存在则创建
// os.O_TRUNC: 打开时清空文件
写入文件
// 方法1: 使用 Write 和 WriteString
content := "Hello, Go!\n"
n, err := file.Write([]byte(content))
// 或者
n, err := file.WriteString(content)
// 方法2: 使用 fmt.Fprintf
fmt.Fprintf(file, "Number: %d, String: %s\n", 42, "Go")
// 方法3: 使用 bufio.Writer
writer := bufio.NewWriter(file)
writer.WriteString("Buffered writing\n")
writer.Flush() // 记得刷新缓冲区
读取文件
// 方法1: 读取整个文件
data, err := os.ReadFile("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 方法2: 逐行读取
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
// 方法3: 使用缓冲区读取
buffer := make([]byte, 1024)
for {
n, err := file.Read(buffer)
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Print(string(buffer[:n]))
}
文件信息
fileInfo, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("文件名:", fileInfo.Name())
fmt.Println("文件大小:", fileInfo.Size(), "bytes")
fmt.Println("修改时间:", fileInfo.ModTime())
fmt.Println("是否是目录:", fileInfo.IsDir())
2. 目录操作
创建目录
// 创建单个目录
err := os.Mkdir("mydir", 0755)
// 创建多级目录
err := os.MkdirAll("path/to/dir", 0755)
读取目录
// 读取目录内容
entries, err := os.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, entry := range entries {
fmt.Println(entry.Name(), entry.IsDir())
}
遍历目录
func walkDir(path string) {
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
fmt.Println("文件:", path)
} else {
fmt.Println("目录:", path)
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
3. 文件操作实用示例
复制文件
func copyFile(src, dst string) error {
input, err := os.ReadFile(src)
if err != nil {
return err
}
err = os.WriteFile(dst, input, 0644)
if err != nil {
return err
}
return nil
}
// 或者使用 io.Copy 处理大文件
func copyFileLarge(src, dst string) error {
source, err := os.Open(src)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
return err
}
检查文件是否存在
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
删除文件/目录
// 删除文件
err := os.Remove("file.txt")
// 删除目录及其内容
err := os.RemoveAll("directory")
4. 临时文件和目录
// 创建临时文件
tempFile, err := os.CreateTemp("", "example.*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tempFile.Name()) // 清理
// 创建临时目录
tempDir, err := os.MkdirTemp("", "example")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tempDir) // 清理
5. 文件权限
// 更改文件权限
err := os.Chmod("file.txt", 0644)
// 更改文件所有者
err := os.Chown("file.txt", os.Getuid(), os.Getgid())
// 获取当前文件权限
fileInfo, _ := os.Stat("file.txt")
mode := fileInfo.Mode()
fmt.Printf("权限: %o\n", mode.Perm()) // 输出八进制权限
6. 错误处理最佳实践
func handleFileOperation() error {
file, err := os.Open("file.txt")
if err != nil {
return fmt.Errorf("打开文件失败: %w", err)
}
defer file.Close()
// 文件操作...
return nil
}
总结
Go 的文件操作接口设计简洁而强大,关键点包括:
- 总是检查错误:文件操作很容易出错,必须处理错误
- 使用 defer 关闭文件:确保资源得到释放
-
根据需求选择读写方式:小文件可用
ReadFile/WriteFile,大文件用流式处理 - 注意文件权限:特别是在多用户环境中
-
处理好路径分隔符:使用
filepath包来处理跨平台路径问题
这些基础操作应该能够满足大多数文件处理需求。对于更复杂的场景,还可以结合 encoding、compress 等包来处理特定格式的文件。