文件操作是大多数程序的基本需求。Go标准库提供了丰富的文件处理功能,主要分布在os、io、bufio、ioutil(Go 1.16后部分功能移至os和io)等包中。本章将介绍文件的创建、打开、读写、复制、删除以及路径操作等常见任务。
ioutil包已被弃用,推荐使用os和io包中的对应函数。
使用os.Open以只读方式打开;os.Create创建或截断文件;os.OpenFile提供更精细的控制。
package main
import (
"fmt"
"os"
)
func main() {
// 1. 只读方式打开
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("打开失败:", err)
return
}
defer file.Close()
// 2. 创建或截断文件(如果存在则覆盖)
file2, err := os.Create("newfile.txt")
if err != nil {
fmt.Println("创建失败:", err)
return
}
defer file2.Close()
// 3. 以指定模式打开(读写、追加、创建等)
file3, err := os.OpenFile("test.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("打开失败:", err)
return
}
defer file3.Close()
}
常用标志:os.O_RDONLY(只读)、os.O_WRONLY(只写)、os.O_RDWR(读写)、os.O_APPEND(追加)、os.O_CREATE(不存在则创建)、os.O_TRUNC(清空文件)。
file, err := os.Create("output.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 写入字符串
_, err = file.WriteString("Hello, Go!\n")
// 写入字节切片
data := []byte("Another line\n")
_, err = file.Write(data)
file, _ := os.Create("buffered.txt")
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("缓冲写入第一行\n")
writer.WriteString("第二行\n")
writer.Flush() // 确保数据写入磁盘
content := []byte("一次性写入的内容")
err := os.WriteFile("one_shot.txt", content, 0644)
file, _ := os.Open("data.txt")
defer file.Close()
buf := make([]byte, 1024)
n, err := file.Read(buf)
fmt.Printf("读取了 %d 字节\n", n)
file, err := os.Open("lines.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
data, err := os.ReadFile("small.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
file, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
if _, err := file.WriteString("新追加的日志行\n"); err != nil {
log.Fatal(err)
}
使用io.Copy实现高效复制。
func copyFile(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
}
// 重命名(移动)
err := os.Rename("old.txt", "new.txt")
if err != nil {
log.Fatal(err)
}
// 删除文件
err := os.Remove("unneeded.txt")
if err != nil {
log.Fatal(err)
}
// 删除目录及其内容
err := os.RemoveAll("temp_dir")
通过os.Stat并判断错误类型。
func fileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
// 使用示例
if fileExists("config.json") {
fmt.Println("配置文件存在")
} else {
fmt.Println("配置文件不存在")
}
info, err := os.Stat("example.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("文件名:", info.Name())
fmt.Println("大小:", info.Size())
fmt.Println("权限:", info.Mode())
fmt.Println("修改时间:", info.ModTime())
fmt.Println("是否为目录:", info.IsDir())
// 创建单个目录(父目录必须存在)
err := os.Mkdir("mydir", 0755)
// 创建多级目录
err := os.MkdirAll("path/to/deep/dir", 0755)
entries, err := os.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, entry := range entries {
fmt.Println(entry.Name(), entry.IsDir())
}
// 创建临时文件(自动生成随机后缀)
tmpFile, err := os.CreateTemp("", "prefix-*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpFile.Name()) // 清理
tmpFile.WriteString("临时数据")
tmpFile.Close()
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "testdir-*")
defer os.RemoveAll(tmpDir)
package main
import (
"fmt"
"log"
"os"
"time"
)
type Logger struct {
file *os.File
}
func NewLogger(filename string) (*Logger, error) {
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
return &Logger{file: file}, nil
}
func (l *Logger) Write(message string) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
line := fmt.Sprintf("[%s] %s\n", timestamp, message)
if _, err := l.file.WriteString(line); err != nil {
log.Println("写入日志失败:", err)
}
}
func (l *Logger) Close() {
l.file.Close()
}
func main() {
logger, err := NewLogger("app.log")
if err != nil {
log.Fatal(err)
}
defer logger.Close()
logger.Write("程序启动")
logger.Write("执行某项操作")
logger.Write("程序正常退出")
fmt.Println("日志写入完成,查看 app.log")
}
os、bufio、io等包的核心函数,足以应对绝大多数的文件处理需求。注意错误处理和资源释放(defer close)。下一章我们将学习Go语言的测试与基准测试。