Go 文件与 IO 操作知识点总结:操作系统底层、源码原理与 bufio 流式高性能实战

Go 文件与 IO 操作知识点总结:操作系统底层、源码原理与 bufio 流式高性能实战

Go 文件与 IO 操作 完整精讲

文章目录

  • Go 文件与 IO 操作 完整精讲
    • 一、先理清三大包定位(面试必区分)
    • 二、底层前置知识:操作系统 IO 基础
      • 文件描述符 File Descriptor(fd)
      • 两种 IO 模式
    • 三、io 包核心接口(抽象层,重中之重)
        • 1. io.ReadAll () 一次性读取全部数据
        • 2. io.Copy(dst Writer, src Reader)
        • 3. io.CopyN(dst Writer, src Reader, n int64)
        • 4. io.LimitReader(r Reader, n int64)
        • 5. io.MultiReader 拼接多个 Reader
        • 6. io.MultiWriter 多目的地同时写入
        • 7. io.TeeReader(r Reader, w Writer)
    • 四、os 包:文件基础操作 + 路径操作
    • 一、文件操作(最高频)
      • 1. os.Open () 只读打开文件
      • 2. os.Create () 创建 / 覆写文件
      • 3. os.OpenFile () 万能打开函数(底层,Open/Create 都是封装它)
        • flag 常用常量(可组合,`|` 连接)
        • perm 文件权限(Linux)
      • 4. File 对象读写方法
      • 5. 文件删除、重命名
    • 二、文件夹操作
    • 三、文件信息查询
    • 四、环境变量相关
    • 五、进程标准流(Stdin/Stdout/Stderr)
    • 六、进程相关
    • 七、路径工具(搭配 os 使用,更多路径操作推荐 path /filepath 包)
  • ⚠️ 高频易错坑
      • 基础读写示例
    • 1. 常用 flag 组合(背诵)
    • 2. 易错坑点
    • 3. 使用场景建议
    • 五、bufio 缓冲 IO:高效流式处理(考点核心)
      • 底层原理
        • bufio.Reader 读流程
        • bufio.Writer 写流程
      • 常用代码示例
      • 高频函数
      • `bufio.Scanner`:最适合**按行遍历大文件**
        • 一、基础创建
        • 二、核心执行流程(固定模板)
        • 三、常用方法清单
          • 1. `Scan() bool`
          • 2. `Text() string`
          • 3. `Bytes() []byte`
          • 4. `Err() error`
          • 5.`Split(split SplitFunc)`
          • 6. `Buffer(buf []byte, max int)`
          • 7. `MaxScanTokenSize`
        • 四、完整可运行示例
        • 五、面试对比:Scanner VS bufio.Reader ReadLine / ReadString
        • 六、高频坑(必背)
        • 📝极简背诵总结
      • 2.bufio.NewReader/bufio.NewWriter 常用方法汇总(面试速记)
      • 一、bufio.Reader(NewReader)
        • 核心方法
        • 记忆重点
      • 二、bufio.Writer(NewWriter)
        • 核心方法
        • 致命坑(必背)
        • 极简对比速查表
    • 六、三种读写方案对比(选型标准)
    • 七、底层深入:os.File 源码结构(简化)
      • bufio.Reader 简化结构
    • 八、关键坑点(面试高频)
    • 九、完整流式大文件 Demo(贴合题干「高效流式处理」)
    • 十、知识点总结背诵版

核心包:os/io/bufio

目标:文件读写、路径操作、高效流式处理,附带操作系统底层原理 + Go 源码层面讲解

一、先理清三大包定位(面试必区分)

  1. os:操作系统资源封装

    • 直接操作文件、目录、进程、权限;
    • os.File代表操作系统打开的文件描述符 (fd)
    • 提供路径、文件创建、删除、文件元信息查询。
  2. io:基础抽象接口(整个 Go IO 体系基石)

    定义标准接口:

    Reader
    Writer
    Closer
    Seeker

    所有可读对象只要实现Read(p []byte)(n int, err error)就是 Reader,实现解耦。

  3. bufio:缓冲 IO,流式高效读写

    在 os.File 之上增加内存缓冲区,减少系统调用次数,优化 IO 性能。

二、底层前置知识:操作系统 IO 基础

文件描述符 File Descriptor(fd)

进程打开文件时,操作系统内核返回一个非负整数 fd;

os.File内部封装了 fd,所有读写操作最终都会调用 Linux 系统调用:

open/read/write/close

两种 IO 模式

  1. 无缓冲 IO(os.File 直接 Read/Write)

    每次调用 Read → 直接发起一次系统调用,频繁读写小数据时开销巨大。

  2. 用户态缓冲 IO(bufio)

    在应用内存开辟一块缓冲区,程序先读写缓冲区;缓冲区满 / 空时,才向内核发起系统调用,大幅减少系统调用次数。

系统调用需要 CPU 从用户态切换内核态,切换成本很高,这就是 bufio 性能优势根源。

三、io 包核心接口(抽象层,重中之重)

// 基础读接口 type Reader interface { Read(p []byte) (n int, err error) } // 基础写接口 type Writer interface { Write(p []byte) (n int, err error) } // 关闭资源 type Closer interface { Close() error } // 偏移读写(文件支持,管道/网络流不支持) type Seeker interface { Seek(offset int64, whence int) (int64, error) }

os.File同时实现了Reader/Writer/Closer/Seeker

工具函数io.Copy(dst Writer, src Reader)

不需要手动开辟缓冲区,自动把源数据拷贝到目标,通用流式拷贝

1. io.ReadAll () 一次性读取全部数据

作用:循环读取 Reader 直到 EOF,返回全部 [] byte

✅适用:小数据

❌禁止:超大文件、无限数据流(会爆内存)

r := bytes.NewBufferString("read all demo") data, err := io.ReadAll(r) if err != nil { panic(err) } fmt.Println(string(data))
2. io.Copy(dst Writer, src Reader)

作用:从 src 读取,写入 dst;内置 32KB 缓冲,不用手动循环 Read

重点:Copy不会自动关闭 src /dst,文件、网络连接需要手动 Close!

src := bytes.NewBufferString("copy test") var dst bytes.Buffer _, err := io.Copy(&dst, src) if err != nil { panic(err) } fmt.Println(dst.String())
3. io.CopyN(dst Writer, src Reader, n int64)

只复制最多 N 个字节,超过部分直接丢弃

// 只拷贝前5个字节 io.CopyN(&dst, src, 5)
4. io.LimitReader(r Reader, n int64)

包装 Reader,限制最多读取 n 字节,常用于防攻击(限制请求 body 最大大小)

r := bytes.NewBufferString("123456789") limitR := io.LimitReader(r, 4) // 最多读4字节 data, _ := io.ReadAll(limitR) fmt.Println(string(data)) // 输出:1234
5. io.MultiReader 拼接多个 Reader

按顺序读取多个数据源,读完第一个自动读取第二个

r1 := bytes.NewBufferString("a") r2 := bytes.NewBufferString("b") rAll := io.MultiReader(r1, r2) data, _ := io.ReadAll(rAll) fmt.Println(string(data)) // ab
6. io.MultiWriter 多目的地同时写入

一份数据,同时写入多个 Writer(类似日志同时输出到控制台 + 文件)

var buf1, buf2 bytes.Buffer w := io.MultiWriter(&buf1, &buf2) _, _ = w.Write([]byte("hello")) fmt.Println(buf1.String(), buf2.String())
7. io.TeeReader(r Reader, w Writer)

一边读取源数据,一边自动复制一份写入 w;实现「读取同时备份」

src := bytes.NewBufferString("content") var backup bytes.Buffer teeR := io.TeeReader(src, &backup) data, _ := io.ReadAll(teeR) fmt.Println("读到的数据:", string(data)) fmt.Println("备份缓冲区:", backup.String())

四、os 包:文件基础操作 + 路径操作

一、文件操作(最高频)

1. os.Open () 只读打开文件

func Open(name string) (*File, error)

特性:只读模式,不能写入;文件不存在返回错误。

file, err := os.Open("test.txt") if err != nil { panic(err) } defer file.Close() // 必须关闭,防止文件句柄泄漏 // 搭配io.ReadAll直接读取全部内容 data, err := io.ReadAll(file) fmt.Println(string(data))

2. os.Create () 创建 / 覆写文件

func Create(name string) (*File, error)

规则:

  1. 文件不存在 → 创建;
  2. 文件已存在 →清空原有内容(截断)
  3. 权限:0666(rw-rw-rw);读写模式。
file, err := os.Create("out.txt") defer file.Close() file.Write([]byte("hello os"))

3. os.OpenFile () 万能打开函数(底层,Open/Create 都是封装它)

简易封装:

  • os.Open(path)→ O_RDONLY 只读打开
  • os.Create(path)→ O_RDWR|O_CREATE|O_TRUNC 创建 / 清空文件
func OpenFile(name string, flag int, perm FileMode) (*File, error)
flag 常用常量(可组合,|连接)
常量含义
os.O_RDONLY只读
os.O_WRONLY只写
os.O_RDWR读写
os.O_APPEND追加写入,不覆盖旧数据
os.O_CREATE不存在则创建
os.O_TRUNC存在就清空截断
perm 文件权限(Linux)
  • 0644:所有者读写,其他人只读(最常用)
  • 0755:可执行文件权限

示例:追加写文件(不会覆盖)

file, err := os.OpenFile("log.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) defer file.Close() file.Write([]byte("追加一行日志\n"))

4. File 对象读写方法

// 实现 io.Reader n, err := file.Read(buf []byte) // 实现 io.Writer n, err := file.Write([]byte) n, err := file.WriteString("文本") // 文件指针跳转(实现 io.Seeker) offset, err := file.Seek(10, io.SeekStart)

5. 文件删除、重命名

// 删除文件 err := os.Remove("test.txt") // 重命名/移动文件 err := os.Rename("old.txt", "new.txt") // RemoveAll:递归删除文件夹+内部所有内容(rm -rf) err := os.RemoveAll("./tmpdir")

二、文件夹操作

// 创建单层目录 err := os.Mkdir("mydir", 0755) // MkdirAll:递归创建多级目录(mkdir -p) err := os.MkdirAll("a/b/c", 0755) // 读取目录下所有文件信息 entries, err := os.ReadDir("./") for _, entry := range entries { fmt.Println(entry.Name(), entry.IsDir()) }

三、文件信息查询

// 获取文件元信息(大小、修改时间、是否目录) info, err := os.Stat("test.txt") fmt.Println("大小:", info.Size()) fmt.Println("是否目录:", info.IsDir()) fmt.Println("修改时间:", info.ModTime()) // os.Lstat():和Stat类似,但不跟随软链接 info, err := os.Lstat("link.txt")

四、环境变量相关

// 获取环境变量,不存在返回空字符串 val := os.Getenv("PATH") // 设置环境变量 err := os.Setenv("TEST_KEY", "123") // 查询环境变量是否存在 val, ok := os.LookupEnv("TEST_KEY") // 清除环境变量 os.Unsetenv("TEST_KEY") // 获取全部环境变量 envs := os.Environ()

五、进程标准流(Stdin/Stdout/Stderr)

os.Stdin // 标准输入(终端输入)*os.File os.Stdout // 标准输出 fmt.Println底层写入这里 os.Stderr // 标准错误输出

示例:直接往控制台输出

os.Stdout.WriteString("打印到终端\n")

六、进程相关

// 获取当前进程PID pid := os.Getpid() // 获取父进程PID ppid := os.Getppid() // 退出程序;非0代表异常退出 os.Exit(1)

七、路径工具(搭配 os 使用,更多路径操作推荐 path /filepath 包)

filepath:跨平台路径处理(Windows / Linux 分隔符自动适配,优先使用)

常用 API:

  • filepath.Join(a,b,c):拼接路径,自动处理分隔符

  • filepath.Abs(path):获取绝对路径

  • filepath.Base(path):获取文件名

  • filepath.Dir(path):获取目录

  • filepath.Glob("*.txt"):通配符匹配文件

// 判断文件是否存在(易错!不能用err==nil直接判断) func FileExists(path string) bool { _, err := os.Stat(path) return !os.IsNotExist(err) } // 判断错误是否为「文件不存在」 os.IsNotExist(err) // 判断是否权限不足 os.IsPermission(err)

⚠️ 高频易错坑

  1. 打开文件必须 defer Close (),长期运行服务会耗尽文件句柄;
  2. os.Create()打开已有文件直接清空!追加场景必须使用OpenFile + O_APPEND
  3. os.Mkdir只能创建单层目录,多级目录请用MkdirAll
  4. os.File实现io.Reader,所以可以直接传入io.Copy、io.ReadAll
  5. Windows 和 Linux 文件路径分隔符不一样,路径拼接优先使用filepath.Join()

基础读写示例

package main import ( "os" ) func main() { // 只读打开 f, err := os.Open("test.txt") if err != nil {panic(err)} defer f.Close() // 必须关闭,释放文件描述符! buf := make([]byte, 1024) n, err := f.Read(buf) // 直接无缓冲读取 _ = n }

⚠️ 重要规范:打开文件一定要 defer Close ()

底层:进程不 close,fd 不会释放;大量泄漏会触发「打开文件数过多」崩溃。

1. 常用 flag 组合(背诵)

// 等价 os.Open(只读打开) f, _ := os.OpenFile("a.txt", os.O_RDONLY, 0) // 等价 os.Create(读写,不存在创建,存在清空) // O_RDWR | O_CREATE | O_TRUNC f, _ := os.OpenFile("a.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) // 追加写入(文件尾部添加,不清空旧内容) f, _ := os.OpenFile("a.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 数字含义拆分 权限格式:0 [所有者][同组用户][其他用户] 0 6 4 4 第一位 0:八进制前缀,无权限含义 第二位 6 → 文件拥有者(user) 第三位 4 → 同组用户(group) 第四位 4 → 外部其他用户(other) 单个数字 = 读 + 写 + 执行权限之和: 4 = 读权限 r 2 = 写权限 w 1 = 执行权限 x 拆解 0644 所有者 6 = 4+2 → r w - 可读、可写,不可执行 同组用户 4 = 4 → r - - 仅可读 其他用户 4 = 4 → r - - 仅可读 字符表示:-rw-r--r--

2. 易错坑点

  1. os.Open 拿到的文件句柄不能 Write ()
f, _ := os.Open("test.txt") f.Write([]byte("hello")) // ❌ 报错,只读文件无法写入
  1. perm 参数仅新建文件时生效

    文件已经存在时,perm 参数会被直接忽略,不会修改已有文件权限。

    想要修改已有文件权限,单独调用os.Chmod()

    err = os.Chmod(fileName, 0644) if err != nil { ​ fmt.Println("修改权限失败:", err) ​ return } fmt.Println("权限修改成功,设置为 0644 (-rw-r--r--)")
  2. flag 三大基础模式三选一,不能同时写多个

  • O_RDONLY只读
  • O_WRONLY只写
  • O_RDWR读写

错误示范:O_RDONLY | O_WRONLY非法!


3. 使用场景建议

  • 只读取文件内容→ 直接用os.Open(简洁)
  • 需要写入、创建、追加、覆盖文件→ 必须使用os.OpenFile

五、bufio 缓冲 IO:高效流式处理(考点核心)

底层原理

bufio.Reader/bufio.Writer内部维护一块[]byte缓冲区。

bufio.Reader 读流程
  1. 用户调用 Read → 先尝试从内存缓冲区拿数据;
  2. 缓冲区空 → 调用底层 os.File.Read,一次性读取一大块数据填满缓冲区;
  3. 后续读取继续复用缓冲区,减少系统调用。
bufio.Writer 写流程
  1. Write 数据先写入内存缓冲区;
  2. 缓冲区满,自动刷入底层文件;
  3. 文件关闭前必须调用 Flush (),把缓冲区残留数据写入磁盘!

常用代码示例

package main import ( "bufio" "os" ) func main() { f, _ := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE, 0644) defer f.Close() // 带缓冲写入 w := bufio.NewWriter(f) w.WriteString("hello go io\n") w.Flush() // 强制刷盘,不可省略! // 带缓冲读取 r := bufio.NewReader(f) // ReadString('\n') 按行读取,流式处理大文件首选 line, _ := r.ReadString('\n') _ = line }

高频函数

bufio.Scanner:最适合按行遍历大文件

scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() // 逐行处理,不需要一次性把整个文件加载进内存(流式) }

优势:处理 GB 级大文件不会 OOM,流式处理,题干重点要求。

一、基础创建
// 从io.Reader创建(文件、strings.Reader都可以) scanner := bufio.NewScanner(r)
二、核心执行流程(固定模板)
scanner := bufio.NewScanner(reader) // 循环扫描,直到读到末尾或者出错 for scanner.Scan() { // 获取当前扫描到的文本 line := scanner.Text() fmt.Println(line) } // ❗必须检查扫描过程中的错误(不能忘!) if err := scanner.Err(); err != nil { fmt.Println("读取失败:", err) }
三、常用方法清单
1.Scan() bool
  • 作用:向前读取下一段数据
  • 返回值:
    • true:成功读到一段内容,可以调用 Text ()/Bytes () 取值
    • false:读取结束(EOF)或者发生错误

⚠️ 注意:Scan 不会返回错误,错误统一在循环结束后用scanner.Err()获取

2.Text() string

获取本次扫描内容,返回string。底层是把字节切片转为字符串。

3.Bytes() []byte

获取本次扫描内容,返回[]byte

✅ 性能更好,注意:下一次调用 Scan () 会覆盖这个切片内容!不要异步保存!

4.Err() error

获取扫描期间产生的错误(排除 io.EOF,EOF 不算错误)

循环结束一定要调用,防止漏掉读写异常。

5.Split(split SplitFunc)

⭐重点:自定义分割函数,控制 Scanner 按什么规则切割数据

内置 4 种分割器(直接背)

// 1. bufio.ScanLines 默认!按行分割,自动去掉 \n \r\n scanner.Split(bufio.ScanLines) // 2. bufio.ScanWords 按空格分割单词 scanner.Split(bufio.ScanWords) // 3. bufio.ScanBytes 逐个字节读取 scanner.Split(bufio.ScanBytes) // 4. bufio.ScanRunes 按utf8字符读取 scanner.Split(bufio.ScanRunes)
6.Buffer(buf []byte, max int)

设置缓冲区,解决单行超过 64KB 默认上限报错

默认限制:单行最大 64KB,超长直接返回错误!

// 设置最大支持 1MB 的单行 buf := make([]byte, 1024*1024) scanner.Buffer(buf, 1024*1024)
7.MaxScanTokenSize

常量:默认最大扫描长度 64 * 1024 = 65536

四、完整可运行示例
package main import ( "bufio" "fmt" "strings" ) func main() { data := strings.NewReader("第一行\n第二行\r\n第三行") sc := bufio.NewScanner(data) // 默认分割:ScanLines for sc.Scan() { str := sc.Text() fmt.Printf("行内容:%q\n", str) } // 检查错误 if err := sc.Err(); err != nil { fmt.Println("err:", err) } }
五、面试对比:Scanner VS bufio.Reader ReadLine / ReadString
  1. bufio.Scanner ✅推荐业务使用

    • API 简洁,自动处理换行\n \r\n
    • 不用手动处理截断、缓冲区碎片
    • 唯一缺点:单行默认上限 64KB,超长要手动扩容
  2. bufio.Reader ReadLine ❌不推荐

    底层原始 API,容易出现超长行截断 bug,需要自己循环拼接碎片

  3. bufio.Reader ReadString(‘\n’)

    可控性更强,适合精细 IO 场景,适合学习底层原理

六、高频坑(必背)
  1. 循环结束必须判断scanner.Err(),很多人漏掉!

  2. scanner.Bytes()

    返回的切片会被下一次 Scan 覆盖,如果需要保存要手动拷贝

    // 错误:直接保存,下次Scan内容会变 tmp := scanner.Bytes() // 正确:拷贝 tmp := append([]byte(nil), scanner.Bytes()...)
  3. 单行超过 64KB 直接报错,大日志文件要调用Buffer()扩容

📝极简背诵总结

bufio.Scanner是封装好的扫描工具,Scan()推进读取,Text()/Bytes()获取内容;支持自定义分割规则;默认按行切割,单行上限 64KB;循环结束务必检查 Err ()。

2.bufio.NewReader/bufio.NewWriter 常用方法汇总(面试速记)

前置:

// 读缓冲 r := bufio.NewReader(io.Reader) // 写缓冲 w := bufio.NewWriter(io.Writer)

一、bufio.Reader(NewReader)

核心方法
  1. ReadString(delim byte) (string, error)

    读到分隔符停止,返回内容包含分隔符

    示例:r.ReadString('\n')按行读取。

    读到文件末尾无分隔符时,返回读到的数据 +io.EOF

  2. ReadBytes(delim byte) ([]byte, error)

    功能和 ReadString 一致,返回[]byte而非字符串。

  3. ReadLine() ([]byte, bool, error)

    按行读取,丢弃换行符\n/\r\n;官方不推荐优先使用,存在缓冲区截断问题。

  4. Read(p []byte) (n int, err error)

    标准 io.Reader 接口方法,填充字节切片。

  5. Peek(n int) ([]byte, error)

    预读 n 个字节,不移动读取指针,只偷看不消费。高频考点。

  6. Discard(n int) (discarded int, err error)

    直接跳过 n 个字节,丢弃数据。

记忆重点

✅ 按行优先:ReadString('\n')

✅ 偷看数据:Peek()

❌ 少用 ReadLine

二、bufio.Writer(NewWriter)

核心方法
  1. Write(p []byte) (n int, err error)

    写入字节切片,数据存入缓冲区,不直接落盘

  2. WriteString(s string) (n int, err error)

    写入字符串,优先使用,省去 string→[] byte 转换开销。

  3. Flush () error 【重中之重】

    强制把缓冲区所有缓存数据写入底层流。

⚠️ 忘记 Flush → 缓冲区残留数据丢失!

  1. Buffered() int

    查询当前缓冲区暂存的字节数量

  2. Available() int

    缓冲区剩余空闲空间大小。

致命坑(必背)

defer 文件.Close()不会自动调用 Flush ()

标准顺序:

w.Flush() f.Close()
极简对比速查表
对象高频方法核心考点
ReaderReadString、Peek、ReadBytesReadString 带回分隔符;Peek 不移动指针
WriterWriteString、Flush、Buffered必须 Flush,否则丢数据

六、三种读写方案对比(选型标准)

  1. os.File 直接 Read/Write(无缓冲)

    适用:单次读写大块数据;不适合频繁小 IO。

    缺点:小循环读写,大量系统调用,性能差。

  2. bufio 缓冲读写

    适用:频繁小数据读写、按行读取大文件、流式处理。

    优点:合并 IO 请求,减少用户态 / 内核态切换,性能高。

  3. os.ReadFile / os.WriteFile

os.ReadFile("a.txt") // 一次性把整个文件读入内存

⚠️致命限制:一次性加载全部内容到内存!

禁止用于超大文件,极易内存溢出,不属于流式处理

七、底层深入:os.File 源码结构(简化)

// src/os/file.go type File struct { *file // 指针 } type file struct { fd int // 文件描述符 name string dirinfo *dirInfo }

所有f.Read()最终调用平台相关系统调用:

Linux:syscall.Read(fd, buf)

bufio.Reader 简化结构

type Reader struct { buf []byte // 缓冲区内存 rd io.Reader // 底层数据源(os.File) r, w int // 读写位置指针 }

缓冲区默认大小 4096 字节,可以手动指定:bufio.NewReaderSize(f, 8192)

八、关键坑点(面试高频)

  1. bufio.Writer 忘记 Flush ()

    程序退出,缓冲区剩余数据丢失!

  2. 忘记 Close () 文件→ 文件描述符泄漏

  3. os.ReadFile读取大文件造成 OOM,不能用于流式场景

  4. filepathpath包区别:

    • path:只处理/分隔符(url 路径)
    • filepath:适配操作系统,本地文件路径必须用它
  5. 权限参数

    0644

    Linux 文件权限:读写权限,创建文件时必须指定。

九、完整流式大文件 Demo(贴合题干「高效流式处理」)

package main import ( "bufio" "fmt" "os" ) func main() { f, err := os.Open("bigfile.log") if err != nil { panic(err) } defer f.Close() scanner := bufio.NewScanner(f) // 逐行流式读取,内存只保存一行数据 lineNo := 0 for scanner.Scan() { lineNo++ content := scanner.Text() fmt.Printf("行%d:%s\n", lineNo, content) } // 检查扫描是否出现错误 if err := scanner.Err(); err != nil { panic(err) } }

特点:无论文件 1GB 还是 10GB,内存占用稳定,典型流式 IO。

十、知识点总结背诵版

  1. io包定义Reader/Writer抽象接口,统一所有可读写资源;
  2. os包封装操作系统文件、fd、路径、目录操作;
  3. bufio在用户态提供缓冲区,减少系统调用,实现高效 IO;
  4. 无缓冲 IO每次读写触发系统调用;缓冲 IO 批量合并请求;
  5. 超大文件处理使用bufio.Scanner流式逐行读取,避免一次性载入内存;
  6. 文件打开务必defer Close();bufio 写入结束必须Flush()