Go 的 io 包定义了几个核心接口,是所有 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 ReadWriter interface {
Reader
Writer
}
type ReadCloser interface {
Reader
Closer
}
type WriteCloser interface {
Writer
Closer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
package main
import (
"fmt"
"io"
)
type StringReader struct {
data []byte
pos int
}
func NewStringReader(s string) *StringReader {
return &StringReader{
data: []byte(s),
}
}
func (r *StringReader) Read(p []byte) (n int, err error) {
if r.pos >= len(r.data) {
return 0, io.EOF
}
n = copy(p, r.data[r.pos:])
r.pos += n
return n, nil
}
func main() {
reader := NewStringReader("Hello, Go!")
buf := make([]byte, 5)
for {
n, err := reader.Read(buf)
if err == io.EOF {
break
}
fmt.Printf("读取: %s\n", buf[:n])
}
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go! This is a long string.")
// 限制只读取 10 字节
limitedReader := io.LimitReader(reader, 10)
data, _ := io.ReadAll(limitedReader)
fmt.Println(string(data)) // Hello, Go!
}
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
var buf bytes.Buffer
// TeeReader 同时读取并写入到 buf
teeReader := io.TeeReader(reader, &buf)
data, _ := io.ReadAll(teeReader)
fmt.Println("读取的数据:", string(data))
fmt.Println("缓冲区数据:", buf.String())
}
package main
import (
"fmt"
"io"
)
type CountWriter struct {
count int
}
func (w *CountWriter) Write(p []byte) (n int, err error) {
w.count += len(p)
return len(p), nil
}
func main() {
writer := &CountWriter{}
io.WriteString(writer, "Hello")
io.WriteString(writer, ", Go!")
fmt.Printf("总共写入: %d 字节\n", writer.count)
}
package main
import (
"bytes"
"fmt"
"io"
"os"
)
func main() {
var buf bytes.Buffer
// 同时写入到文件和缓冲区
multiWriter := io.MultiWriter(os.Stdout, &buf)
io.WriteString(multiWriter, "Hello, Go!\n")
fmt.Println("缓冲区内容:", buf.String())
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
var writer strings.Builder
// 复制数据
n, err := io.Copy(&writer, reader)
if err != nil {
fmt.Println("复制失败:", err)
return
}
fmt.Printf("复制了 %d 字节\n", n)
fmt.Println("内容:", writer.String())
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
var writer strings.Builder
// 使用自定义缓冲区
buf := make([]byte, 4)
n, err := io.CopyBuffer(&writer, reader, buf)
if err != nil {
fmt.Println("复制失败:", err)
return
}
fmt.Printf("复制了 %d 字节\n", n)
fmt.Println("内容:", writer.String())
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
var writer strings.Builder
// 只复制 5 字节
n, err := io.CopyN(&writer, reader, 5)
if err != nil {
fmt.Println("复制失败:", err)
return
}
fmt.Printf("复制了 %d 字节\n", n)
fmt.Println("内容:", writer.String()) // Hello
}
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
reader := bufio.NewReader(strings.NewReader("Hello\nGo\nWorld"))
// 读取一行
line, _ := reader.ReadString('\n')
fmt.Print("第一行:", line)
// 读取一行
line, _ = reader.ReadString('\n')
fmt.Print("第二行:", line)
// 读取剩余内容
remaining, _ := reader.ReadString('\n')
fmt.Print("剩余:", remaining)
}
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, _ := os.Create("output.txt")
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("第一行\n")
writer.WriteString("第二行\n")
writer.WriteString("第三行\n")
// 刷新缓冲区
writer.Flush()
fmt.Println("写入完成")
}
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
text := `第一行
第二行
第三行`
scanner := bufio.NewScanner(strings.NewReader(text))
lineNum := 1
for scanner.Scan() {
fmt.Printf("第 %d 行: %s\n", lineNum, scanner.Text())
lineNum++
}
if err := scanner.Err(); err != nil {
fmt.Println("扫描错误:", err)
}
}
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
text := "apple,banana,orange,grape"
scanner := bufio.NewScanner(strings.NewReader(text))
// 自定义分割函数(按逗号分割)
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
for i := 0; i < len(data); i++ {
if data[i] == ',' {
return i + 1, data[:i], nil
}
}
if atEOF && len(data) > 0 {
return len(data), data, nil
}
return 0, nil, nil
})
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
package main
import (
"fmt"
"io"
)
func main() {
r, w := io.Pipe()
// 写入协程
go func() {
defer w.Close()
w.Write([]byte("Hello, "))
w.Write([]byte("Go!"))
}()
// 读取
data, _ := io.ReadAll(r)
fmt.Println(string(data))
}
package main
import (
"compress/gzip"
"fmt"
"io"
"strings"
)
func main() {
r, w := io.Pipe()
// 压缩协程
go func() {
defer w.Close()
gw := gzip.NewWriter(w)
defer gw.Close()
io.WriteString(gw, "Hello, Go! This is a test string for compression.")
}()
// 读取压缩数据
data, _ := io.ReadAll(r)
fmt.Printf("压缩后大小: %d 字节\n", len(data))
}
package main
import (
"fmt"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
// 读取所有
data, _ := io.ReadAll(reader)
fmt.Println(string(data))
// 重置位置
reader.Seek(0, 0)
// 读取部分
buf := make([]byte, 5)
reader.Read(buf)
fmt.Println(string(buf)) // Hello
}
package main
import (
"fmt"
"strings"
)
func main() {
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(", ")
builder.WriteString("Go!")
fmt.Println(builder.String())
fmt.Printf("长度: %d\n", builder.Len())
// 重置
builder.Reset()
builder.WriteString("New content")
fmt.Println(builder.String())
}
package main
import (
"bytes"
"fmt"
)
func main() {
var buf bytes.Buffer
buf.WriteString("Hello")
buf.WriteString(", Go!")
fmt.Println(buf.String())
// 读取
data := make([]byte, 5)
buf.Read(data)
fmt.Println(string(data)) // Hello
// 剩余内容
fmt.Println(buf.String()) // , Go!
}
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 写入到标准输出
io.WriteString(os.Stdout, "Hello, Go!\n")
// 写入到文件
file, _ := os.Create("output.txt")
defer file.Close()
io.WriteString(file, "Hello, File!\n")
// 写入到 strings.Builder
var builder strings.Builder
io.WriteString(&builder, "Hello, Builder!")
fmt.Println(builder.String())
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
data, _ := io.ReadAll(reader)
fmt.Println(string(data))
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
buf := make([]byte, 5)
// 精确读取 5 字节
n, err := io.ReadFull(reader, buf)
fmt.Printf("读取了 %d 字节: %s\n", n, string(buf))
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
reader := strings.NewReader("Hello, Go!")
buf := make([]byte, 10)
// 至少读取 5 字节
n, err := io.ReadAtLeast(reader, buf, 5)
fmt.Printf("读取了 %d 字节: %s\n", n, string(buf[:n]))
}
本章深入讲解了 Go 语言的 IO 操作:
IO 操作是 Go 语言的核心功能,掌握它能让你更好地处理数据流。在下一章中,我们将学习 JSON 和 XML 处理。