首页 / Go 语言入门教程 / os 与 io 包

Go 语言入门教程

os 与 io 包

本教程共 80 篇 · 第 73 篇 · 更新于 2026-07-27 · 约 8 分钟阅读

GoGo 入门教程osio文件读写ReaderWriterio.Copy

73. os 与 io 包

本节目标:学会用 os 包读写文件,理解 io.Reader/Writer 接口,掌握 io.Copy 和环境变量操作。

os 包读文件

最简单的方式,os.ReadFile 一把读完(Go 1.16+):

data, err := os.ReadFile("config.txt")
if err != nil {
	fmt.Println("读文件失败:", err)
	return
}
fmt.Println(string(data))

适合小文件。大文件用流式读取更省内存。

os 包写文件

os.WriteFile 一把写入:

err := os.WriteFile("output.txt", []byte("hello world"), 0644)
if err != nil {
	fmt.Println("写文件失败:", err)
}

第三个参数是文件权限,和 Linux 的 chmod 一样。0644 表示所有者可读写,其他人只读。

打开和创建文件

需要更多控制时,用 os.Openos.Create

// 只读打开
file, err := os.Open("input.txt")
if err != nil {
	log.Fatal(err)
}
defer file.Close()

// 创建或截断(覆盖)
file, err := os.Create("output.txt")
if err != nil {
	log.Fatal(err)
}
defer file.Close()

// 更精细的控制
file, err := os.OpenFile("app.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)

常用打开标志:

标志含义
os.O_RDONLY只读
os.O_WRONLY只写
os.O_RDWR读写
os.O_CREATE不存在就创建
os.O_APPEND追加
os.O_TRUNC存在就截断
Tip

打开的文件记得 defer file.Close(),否则文件描述符泄漏,长时间运行会耗尽。

读写数据

*os.File 实现了 io.Readerio.Writer 接口,可以直接读写:

file, _ := os.Create("test.txt")
defer file.Close()

// 写
n, err := file.Write([]byte("hello"))
// 或.WriteString("hello")

// 读
buf := make([]byte, 1024)
n, err := file.Read(buf)

Read 返回实际读取的字节数。读到末尾返回 io.EOF

io.Reader 接口

io.Reader 是 Go 里最核心的接口之一,只有一方法:

type Reader interface {
	Read(p []byte) (n int, err error)
}

文件、网络连接、压缩流、字符串都实现了它。只要是 Reader,就能用同一套代码读:

func countLines(r io.Reader) int {
	scanner := bufio.NewScanner(r)
	count := 0
	for scanner.Scan() {
		count++
	}
	return count
}

// 文件、网络、字符串都能传
countLines(file)
countLines(strings.NewReader("a\nb\nc"))
countLines(resp.Body)

io.Writer 接口

type Writer interface {
	Write(p []byte) (n int, err error)
}

同样,文件、网络连接、缓冲区都实现了它。

io.Copy

io.Copy 把数据从 Reader 拷贝到 Writer,直到遇到 EOF:

// 文件拷贝
src, _ := os.Open("source.txt")
defer src.Close()
dst, _ := os.Create("dest.txt")
defer dst.Close()

n, err := io.Copy(dst, src)
fmt.Println("拷贝了", n, "字节")

不用自己写循环读写了,io.Copy 帮你搞定,还高效。

bufio 缓冲读写

直接 Read/Write 每次都走系统调用,频繁操作性能差。bufio 包提供缓冲:

// 缓冲读
file, _ := os.Open("data.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
	line := scanner.Text() // 逐行读
	fmt.Println(line)
}

// 缓冲写
file, _ := os.Create("out.txt")
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("buffered line\n")
writer.Flush() // 别忘了刷新
Note

bufio.Scanner 默认按行扫描,单行上限 64KB。超大行要用 Scanner.Buffer 调大缓冲。

环境变量

// 读取
home := os.Getenv("HOME")          // 不存在返回空字符串
val, ok := os.LookupEnv("DEBUG")   // 区分空值和不存在

// 设置
os.Setenv("MY_VAR", "hello")

// 列出所有
for _, e := range os.Environ() {
	fmt.Println(e)
}
Tip

os.Getenv 不存在时返回空字符串,没法区分「值为空」和「没设」。要区分就用 os.LookupEnv

其他常用功能

os.Mkdir("logs", 0755)              // 创建目录
os.MkdirAll("logs/app/2026", 0755)  // 递归创建
os.Remove("temp.txt")                // 删文件
os.RemoveAll("tempdir")              // 递归删目录
os.Rename("old.txt", "new.txt")      // 重命名
os.Exit(1)                           // 立即退出程序
os.Args                              // 命令行参数
os.TempDir()                         // 临时目录

小结

  • os.ReadFile/os.WriteFile:简单读写小文件
  • os.Open/os.Create/os.OpenFile:精细控制打开方式
  • 打开文件务必 defer Close()
  • io.Reader/io.Writer 是核心接口,统一读写抽象
  • io.Copy 高效拷贝数据流
  • bufio 包提供缓冲读写和 Scanner 逐行读
  • os.Getenv/Setenv 操作环境变量

下一节讲 time 包。