概述

在使用Go语言的过程中,无论是实现web应用程序,还是控制台输入输出,又或者是网络操作,不可避免的会遇到IO操作,使用到io.Reader和io.Writer接口。

io

io.Reader

io.Reader 表示一个读取器,它将数据从某个资源读取到传输缓冲区。在缓冲区中,数据可以被流式传输和使用。

io reader

io.Reader接口定义如下:

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

io.Reader接口定义了Read(p []byte) (n int, err error)方法,我们可以使用它从Reader中读取一批数据。在Reader中:

  • 一次最多读取len(p)长度的数据
  • 读取遭遇到error(io.EOF或者其它错误), 会返回已读取的数据的字节数和error
  • 即使读取字节数< len(p),也不会更改p的大小
  • 当输入流结束时,调用它可能返回 err == EOF 或者 err == nil,并且n >=0, 但是下一次调用肯定返回 n=0, err=io.EOF

io.Writer

io.Writer 表示一个编写器,它从缓冲区读取数据,并将数据写入目标资源。

io writer

io.Writer接口定义如下:

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

Write() 方法有两个返回值,一个是写入到目标资源的字节数,一个是发生错误时的错误。

接口继承关系

围绕着io.Reader io.Writer接口的实现,主要有:

  • net.Conn, os.Stdin, os.File: 网络、标准输入输出、文件的流读取

  • strings.Reader: 把字符串抽象成Reader

  • bytes.Reader: 把[]byte抽象成Reader

  • bytes.Buffer: 把[]byte抽象成Reader和Writer

  • bufio.Reader/Writer: 抽象成带缓冲的流读取(比如按行读写)

接口继承关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
func stringReader() {
reader := strings.NewReader("hello world")
b := make([]byte, 4)

for {
n, err := reader.Read(b)
if err != nil {
if err == io.EOF {
fmt.Println("finish read")
break
}

fmt.Println(err)
os.Exit(1)
}
fmt.Println(n, string(b[:n]))
}
}

func bufferWriter() {
providers := []string{
"hello",
"world",
"golang",
"is great",
}

var writer bytes.Buffer
for _, s := range providers {
n, err := writer.Write([]byte(s))
if err != nil {
fmt.Println(err)
os.Exit(1)
}

if n != len(s) {
fmt.Println("failed to write data")
os.Exit(1)
}
}

fmt.Println(writer.String())
}

func fileWriter() {
file, err := os.Create("./files.txt")
if err != nil {
fmt.Println(err)
os.Exit(1)
}

defer file.Close()

providers := []string{
"hello",
"world",
"golang",
"is great",
}

for _, p := range providers {
c, err := file.Write([]byte(p))
if err != nil {
fmt.Println(err)
os.Exit(1)
}

if c != len(p) {
fmt.Println("failed to write data")
os.Exit(1)
}
}
}

//file reader
func fileReader() {
file, err := os.Open("./files.txt")
if err != nil {
fmt.Println(err)
os.Exit(1)
}

defer file.Close()

p := make([]byte, 4)
for {
n, err := file.Read(p)
if err != nil {
if err == io.EOF {
break
}

fmt.Println(err)
}

fmt.Println(string(p[:n]))
}
}

//buffio
func bufReader() {
file, err := os.Open("./files.txt")
if err != nil {
panic(err)
}

defer file.Close()

p := make([]byte, 4)
reader := bufio.NewReader(file)
for {
n, err := reader.Read(p)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}

fmt.Println(string(p[:n]))
}
}

//ioutil 包
func ioutilReader() {
bytes, err := ioutil.ReadFile("./files.txt")
if err != nil {
panic(err)
}

fmt.Println(string(bytes))
}

参考文档