Skip to content

Commit 6b16ae5

Browse files
committed
完成bufio包。第一章基本完成
1 parent bed5a9d commit 6b16ae5

File tree

1 file changed

+113
-6
lines changed

1 file changed

+113
-6
lines changed

chapter01/01.4.md

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ bufio 包实现了缓存IO。它包装了 io.Reader 和 io.Writer 对象,创
44

55
## 1.4.1 Reader 类型和方法 ##
66

7-
bufio.Reader 结构包装了一个 io.Reader 对象,同时实现了 io.Reader 接口。
7+
bufio.Reader 结构包装了一个 io.Reader 对象,提供缓存功能,同时实现了 io.Reader 接口。
88

99
Reader 结构没有任何导出的字段,结构定义如下:
1010

@@ -19,9 +19,9 @@ Reader 结构没有任何导出的字段,结构定义如下:
1919
lastRuneSize int // 最后一次读到的Rune的大小(ReadRune/UnreadRune)
2020
}
2121

22-
### 1.4.1.1 实例化方法 ###
22+
### 1.4.1.1 实例化 ###
2323

24-
bufio 包提供了两个实例化 bufio.Reader 对象的方法:NewReader和NewReaderSize。其中,NewReader方法是调用NewReaderSize方法实现的
24+
bufio 包提供了两个实例化 bufio.Reader 对象的函数:NewReader 和 NewReaderSize。其中,NewReader 函数是调用 NewReaderSize 函数实现的
2525

2626
func NewReader(rd io.Reader) *Reader {
2727
// 默认缓存大小:defaultBufSize=4096
@@ -200,6 +200,17 @@ ReadLine返回的文本不会包含行结尾("\r\n"或者"\n")。如果输
200200

201201
Reader的其他方法都是实现了io包中的接口,它们的使用方法在io包中都有介绍,在此不赘述。
202202

203+
这些方法包括:
204+
205+
func (b *Reader) Read(p []byte) (n int, err error)
206+
func (b *Reader) ReadByte() (c byte, err error)
207+
func (b *Reader) ReadRune() (r rune, size int, err error)
208+
func (b *Reader) UnreadByte() error
209+
func (b *Reader) UnreadRune() error
210+
func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
211+
212+
你应该知道它们都是哪个接口的方法吧。
213+
203214
## 1.4.2 Scanner 类型和方法 ##
204215

205216
对于简单的读取一行,在Reader类型中,感觉没有让人特别满意的方法。于是,Go1.1增加了一个类型:Scanner。官方关于**Go1.1**增加该类型的说明如下:
@@ -276,9 +287,9 @@ SplitFunc 定义了 用于对输入进行分词的 split 函数的签名。参
276287

277288
**token 字段** 上文已经解释了这个是什么意思。
278289

279-
### 1.4.2.2 Scanner 的实例化方法 ###
290+
### 1.4.2.2 Scanner 的实例化 ###
280291

281-
Scanner 没有导出任何字段,而它需要有外部的 io.Reader 对象,因此,我们不能直接实例化 Scanner 对象,必须通过 bufio 包提供的实例化方法来实例化。实例化方法签名以及内部实现
292+
Scanner 没有导出任何字段,而它需要有外部的 io.Reader 对象,因此,我们不能直接实例化 Scanner 对象,必须通过 bufio 包提供的实例化函数来实例化。实例化函数签名以及内部实现
282293

283294
func NewScanner(r io.Reader) *Scanner {
284295
return &Scanner{
@@ -291,7 +302,7 @@ Scanner 没有导出任何字段,而它需要有外部的 io.Reader 对象,
291302

292303
可见,返回的 Scanner 实例默认的 split 函数是 ScanLines。
293304

294-
### 1.4.2.2 Scanner 其他方法 ###
305+
### 1.4.2.2 Scanner 的方法 ###
295306

296307
**Split 方法** 前面我们提到过可以通过 Split 方法为 Scanner 实例设置分词行为。由于 Scanner 实例的默认 split 总是 ScanLines,如果我们想要用其他的 split,可以通过 Split 方法做到。
297308

@@ -354,7 +365,103 @@ Scanner 没有导出任何字段,而它需要有外部的 io.Reader 对象,
354365
It is the home of gophers.
355366
If you are studying golang, welcome you!
356367

368+
## 1.4.3 Writer 类型和方法 ##
369+
370+
bufio.Writer 结构包装了一个 io.Writer 对象,提供缓存功能,同时实现了 io.Writer 接口。
371+
372+
Writer 结构没有任何导出的字段,结构定义如下:
373+
374+
type Writer struct {
375+
err error // 写过程中遇到的错误
376+
buf []byte // 缓存
377+
n int // 当前缓存中的字节数
378+
wr io.Writer // 底层的 io.Writer 对象
379+
}
380+
381+
相比 bufio.Reader, bufio.Writer 结构定义简单很多。
382+
383+
注意:如果在写数据到 Writer 的时候出现了一个错误,不会再允许有数据被写进来了,并且所有随后的写操作都会返回该错误。
384+
385+
### 1.4.3.1 实例化 ###
386+
387+
和 Reader 类型一样,bufio 包提供了两个实例化 bufio.Writer 对象的函数:NewWriter 和 NewWriterSize。其中,NewWriter 函数是调用 NewWriterSize 函数实现的:
388+
389+
func NewWriter(wr io.Writer) *Writer {
390+
// 默认缓存大小:defaultBufSize=4096
391+
return NewWriterSize(wr, defaultBufSize)
392+
}
393+
394+
我们看一下 NewWriterSize 的源码:
395+
396+
func NewWriterSize(wr io.Writer, size int) *Writer {
397+
// 已经是 bufio.Writer 类型,且缓存大小不小于 size,则直接返回
398+
b, ok := wr.(*Writer)
399+
if ok && len(b.buf) >= size {
400+
return b
401+
}
402+
if size <= 0 {
403+
size = defaultBufSize
404+
}
405+
// new 一个 bufio.Writer 实例
406+
b = new(Writer)
407+
b.buf = make([]byte, size)
408+
b.wr = wr
409+
return b
410+
}
411+
412+
**题外话**
357413

414+
对比 Reader 和 Writer 的实例化函数,发现它们很相似。然而,在实际实例化时,两者用了不同的方式:&Reader{} 和 new(Writer),让人感觉这不是同一个人写的。
415+
416+
### 1.4.3.2 Available 和 Buffered 方法 ###
417+
418+
Available 方法获取缓存中还未使用的字节数(缓存大小 - 字段 n 的值);Buffered 方法获取写入当前缓存中的字节数(字段 n 的值)
419+
420+
### 1.4.3.3 Flush 方法 ###
421+
422+
该方法将缓存中的所有数据写入底层的 io.Writer 对象中。使用 bufio.Writer 时,在所有的 Write 操作完成之后,应该调用 Flush 方法使得缓存都写入 io.Writer 对象中。
423+
424+
### 1.4.3.4 其他方法 ###
425+
426+
Writer 类型其他方法是一些实际的写方法:
427+
428+
// 实现了 io.ReaderFrom 接口
429+
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
430+
431+
// 实现了 io.Writer 接口
432+
func (b *Writer) Write(p []byte) (nn int, err error)
433+
434+
// 实现了 io.ByteWriter 接口
435+
func (b *Writer) WriteByte(c byte) error
436+
437+
// io 中没有该方法的接口,它用于写入单个 Unicode 码点,返回写入的字节数(码点占用的字节),内部实现会根据当前 rune 的范围调用 WriteByte 或 WriteString
438+
func (b *Writer) WriteRune(r rune) (size int, err error)
439+
440+
// 写入字符串,如果返回写入的字节数比 len(s) 小,返回的error会解释原因
441+
func (b *Writer) WriteString(s string) (int, error)
442+
443+
这些写方法在缓存满了时会调用 Flush 方法。另外,这些写方法源码开始处,有这样的代码:
444+
445+
if b.err != nil {
446+
return b.err
447+
}
448+
449+
也就是说,只要写的过程中遇到了错误,再次调用写操作会直接返回该错误。
450+
451+
## 1.4.4 ReadWriter 类型和实例化 ##
452+
453+
ReadWriter 结构存储了 bufio.Reader 和 bufio.Writer 类型的指针(内嵌),它实现了 io.ReadWriter 结构。
454+
455+
type ReadWriter struct {
456+
*Reader
457+
*Writer
458+
}
459+
460+
ReadWriter 的实例化可以跟普通结构类型一样,也可以通过调用 bufio.NewReadWriter 函数来实现:只是简单的实例化 ReadWriter
461+
462+
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
463+
return &ReadWriter{r, w}
464+
}
358465

359466
# 导航 #
360467

0 commit comments

Comments
 (0)