io 包基本用法
io 包提供了 I/O 原语的基本接口,在 Go 语言中,几乎所有 I/O 相关的操作都实现了这些接口。
核心接口
Reader 和 Writer
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
// Reader 接口示例
reader := strings.NewReader("Hello, World!")
// 读取数据
buf := make([]byte, 5)
n, err := reader.Read(buf)
if err != nil {
panic(err)
}
fmt.Printf("读取了 %d 字节: %s\n", n, buf[:n])
// 继续读取
n, err = reader.Read(buf)
if err != nil {
panic(err)
}
fmt.Printf("读取了 %d 字节: %s\n", n, buf[:n])
// Writer 接口示例
var buffer bytes.Buffer
writer := &buffer
n, err = writer.Write([]byte("Hello"))
if err != nil {
panic(err)
}
fmt.Printf("写入了 %d 字节\n", n)
n, err = writer.Write([]byte(", World!"))
if err != nil {
panic(err)
}
fmt.Printf("总计写入: %s\n", buffer.String())
}
Copy 函数
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
// io.Copy: 从 Reader 复制到 Writer
src := strings.NewReader("这是要复制的数据")
var dst bytes.Buffer
n, err := io.Copy(&dst, src)
if err != nil {
panic(err)
}
fmt.Printf("复制了 %d 字节: %s\n", n, dst.String())
// io.CopyN: 复制指定字节数
src2 := strings.NewReader("Hello, World!")
var dst2 bytes.Buffer
n, err = io.CopyN(&dst2, src2, 5)
if err != nil {
panic(err)
}
fmt.Printf("复制了 %d 字节: %s\n", n, dst2.String())
// io.CopyBuffer: 使用自定义缓冲区
src3 := strings.NewReader("使用自定义缓冲区复制数据")
var dst3 bytes.Buffer
buf := make([]byte, 8)
n, err = io.CopyBuffer(&dst3, src3, buf)
if err != nil {
panic(err)
}
fmt.Printf("复制了 %d 字节: %s\n", n, dst3.String())
}
ReadAll 和 ReadFull
package main
import (
"fmt"
"io"
"strings"
)
func main() {
// io.ReadAll: 读取所有数据
reader := strings.NewReader("这是完整的文本内容")
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
fmt.Printf("读取全部: %s\n", string(data))
// io.ReadFull: 精确读取指定长度
reader2 := strings.NewReader("Hello, World!")
buf := make([]byte, 5)
n, err := io.ReadFull(reader2, buf)
if err != nil {
panic(err)
}
fmt.Printf("精确读取 %d 字节: %s\n", n, string(buf))
// 如果数据不足会返回 io.ErrUnexpectedEOF
shortReader := strings.NewReader("Hi")
bigBuf := make([]byte, 10)
n, err = io.ReadFull(shortReader, bigBuf)
if err == io.ErrUnexpectedEOF {
fmt.Printf("数据不足,只读取了 %d 字节: %s\n", n, string(bigBuf[:n]))
}
}
MultiReader 和 MultiWriter
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
// io.MultiReader: 将多个 Reader 串联
r1 := strings.NewReader("第一部分 ")
r2 := strings.NewReader("第二部分 ")
r3 := strings.NewReader("第三部分")
multiReader := io.MultiReader(r1, r2, r3)
result, err := io.ReadAll(multiReader)
if err != nil {
panic(err)
}
fmt.Printf("MultiReader 结果: %s\n", string(result))
// io.MultiWriter: 同时写入多个 Writer
var buf1, buf2 bytes.Buffer
multiWriter := io.MultiWriter(&buf1, &buf2)
n, err := multiWriter.Write([]byte("同时写入两个缓冲区"))
if err != nil {
panic(err)
}
fmt.Printf("写入字节数: %d\n", n)
fmt.Printf("buf1: %s\n", buf1.String())
fmt.Printf("buf2: %s\n", buf2.String())
}
总结
| 功能 | 函数/类型 | 说明 |
|---|---|---|
| 复制 | io.Copy |
从 Reader 复制到 Writer |
| 读取全部 | io.ReadAll |
读取所有数据到内存 |
| 限制读取 | io.LimitReader |
限制最大读取字节数 |
| 多路读取 | io.MultiReader |
串联多个 Reader |
| 多路写入 | io.MultiWriter |
同时写入多个 Writer |
| 分流读取 | io.TeeReader |
读取时同时备份 |
| 区域读取 | io.SectionReader |
读取指定区域 |
| 管道 | io.Pipe |
内存管道通信 |