引入

Go sort 包 能排序数据,但数据通常来自文件或需要写入文件。Go 的文件操作围绕 os 包和 bufio 包展开,打开、读取、写入、关闭文件是日常开发的基本功。

正文

定义

定义

Go 文件操作主要通过 os 打开和创建文件,用 io 的方法读写内容,用 bufio 实现带缓冲的高效读写。os.Open 打开文件返回 *os.File,它同时实现了 io.Readerio.Writer 接口。

语法

import "os"
 
// 打开文件
f, err := os.Open("data.txt")
defer f.Close()
 
// 创建文件
f, err := os.Create("output.txt")
defer f.Close()
 
// 读取全部内容
data, err := os.ReadFile("data.txt")
 
// 写入全部内容
err = os.WriteFile("output.txt", data, 0644)

例子

os.Open 读取文件

f, err := os.Open("data.txt")
if err != nil {
    log.Fatal(err)
}
defer f.Close()
 
buf := make([]byte, 1024)
n, err := f.Read(buf)
fmt.Println(string(buf[:n]))

os.Open只读模式打开文件。Read 方法把内容读入字节切片,返回实际读取的字节数。用完必须 Close()

os.Create 写入文件

f, err := os.Create("output.txt")
if err != nil {
    log.Fatal(err)
}
defer f.Close()
 
f.WriteString("hello world\n")
f.Write([]byte("second line\n"))

os.Create 创建新文件或截断已有文件。返回的 *os.File 可写。

os.ReadFile 和 os.WriteFile

// 一次性读取全部内容
data, err := os.ReadFile("data.txt")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))
 
// 一次性写入全部内容
err = os.WriteFile("output.txt", []byte("hello"), 0644)

os.ReadFileos.WriteFile最简便的读写方式,不需要手动打开关闭文件。适合小文件,大文件用流式读取。

os.OpenFile 自定义打开模式

// 追加模式打开
f, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
    log.Fatal(err)
}
defer f.Close()
 
f.WriteString("new log entry\n")

os.OpenFile 能指定打开模式和权限。常用标志:

标志说明
os.O_RDONLY只读
os.O_WRONLY只写
os.O_RDWR读写
os.O_CREATE不存在则创建
os.O_APPEND追加写入
os.O_TRUNC截断文件

bufio 带缓冲读取

f, _ := os.Open("data.txt")
defer f.Close()
 
scanner := bufio.NewScanner(f)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}
 
if err := scanner.Err(); err != nil {
    log.Fatal(err)
}

bufio.NewScanner 按行读取文件,内存效率高,适合逐行处理大文件。scanner.Text() 返回当前行文本。

bufio 带缓冲写入

f, _ := os.Create("output.txt")
defer f.Close()
 
w := bufio.NewWriter(f)
w.WriteString("line 1\n")
w.WriteString("line 2\n")
w.Flush()  // 必须调用,把缓冲区内容写入文件

bufio.NewWriter 在内存中缓冲写入,减少磁盘 IO 次数Flush() 必须调用,否则缓冲内容不会写入文件。

按字节分割读取

f, _ := os.Open("data.csv")
defer f.Close()
 
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanWords)  // 按空格分割
 
for scanner.Scan() {
    fmt.Println(scanner.Word())
}

scanner.Split 设置分割方式:ScanLines(按行,默认)、ScanWords(按空格)、ScanRunes(按字符)、ScanBytes(按字节)。

文件信息

info, err := os.Stat("data.txt")
if err != nil {
    log.Fatal(err)
}
 
fmt.Println(info.Name())     // data.txt
fmt.Println(info.Size())     // 文件字节数
fmt.Println(info.Mode())     // 权限
fmt.Println(info.ModTime())  // 修改时间
fmt.Println(info.IsDir())    // 是否目录

os.Stat 获取文件信息。用 os.IsNotExist(err) 判断文件是否不存在。

常见写法

写法说明
os.Open(name)只读打开文件
os.Create(name)创建或截断文件
os.OpenFile(name, flag, perm)自定义模式打开文件
os.ReadFile(name)一次性读取文件内容
os.WriteFile(name, data, perm)一次性写入文件
f.Close()关闭文件
f.Read(buf) / f.Write(buf)读写文件内容
bufio.NewScanner(f)带缓冲逐行读取
bufio.NewWriter(f)带缓冲写入
os.Stat(name)获取文件信息
os.IsNotExist(err)判断文件是否存在
os.Remove(name)删除文件

特点

  • os.Open 只读,os.Create 可写且截断,os.OpenFile 最灵活
  • 打开的文件必须 Close(),用 defer 确保执行
  • os.ReadFile / os.WriteFile 最简单,适合小文件一次性读写
  • bufio.Scanner 逐行读取,内存效率高,处理大文件首选
  • bufio.NewWriter 缓冲写入,Flush() 必须调用
  • *os.File 同时实现了 io.Readerio.Writer,能配合 Go io 包 的函数使用

理解

Go 文件操作的核心思路:os.Open / os.Create 打开文件拿到 *os.File,然后用 Read / Writebufio 读写内容,最后 defer f.Close() 收尾。小文件用 os.ReadFile 最省事,大文件用 bufio.Scanner 逐行处理。OpenFile 的 flag 组合看着多,记住 O_CREATE(创建)和 O_APPEND(追加)就够日常用了。

引出

文件操作是本地数据处理的基础,但很多应用还需要通过网络传输数据。接下来看 Go 网络编程,学习 TCP、UDP 等底层网络协议在 Go 中的实现。