3

golang中的buffer是什么?

 1 year ago
source link: https://studygolang.com/articles/13703?fr=sidebar
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

golang中的buffer是什么?

豆瓣奶茶 · 2018-07-20 18:34:46 · 1007 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-07-20 18:34:46 的文章,其中的信息可能已经有所发展或是发生改变。

io重要的接口

在介绍buffer之前,先来认识两个重要的接口,如下边所示:

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

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

上边两个接口在golang sdk安装目录src/io/io.go中定义。后边凡是涉及到io相关操作的,基本上都实现了这两个接口,如:

1. package bufio 中的Reader类
2. package bytes 中的Reader类与Buffer类
3. package os 中 的File类,这个实现的最为复杂,主要由于在文件操作中,需要系统底层提供服务。
...不再一一列举...

经常听说有这么一句话:“使用I/O buffer,有助于提高效率”。但是,我想反问的是,真的提高了效率了吗?
buffer在什么情况下会提高我们的程序性能呢?带着这个问题,我们来剖析一下上边提到的几个类。

1.第一个类bytes.Reader

这个类,实现了io.Reader接口,但是这个类没有实现io.Writer接口。这个类没有buffer,为啥?因为这个类,在初始化时,将字符流传入到对象中保存,没有提供Write方法写入新的字符流。所以,这个类不需要buffer。

2.第二个类bytes.Buffer

这个类实现了io.Reader与io.Writer接口,这个类在写入字节流的过程中,使用到了buffer,怎么实现的呢?
在初始化这个类时,会传入一个[]byte类型的slice到对象中,当Write方法向这个对象中写入字节流时,如果之前传入的这个[]byte申请的空间不够时,Write会调用自身的Grow方法,给这个[]byte类型的slice类型扩容,这样,这个里边的buffer会随着写入量增大,长度会不断的扩大。如果此处没有buffer的话,当写入容量满时,要么阻塞,要么循环写入,这样会导致系统卡死或数据被破坏,当引入buffer后,解决了上边的两个问题。但是这种解决方式,存在一个隐患,也就是如果出现读取死循环,这样会造成内存溢出。

3.第三个类bufio.Reader

这个类实现了io.Reader接口,这个类在实例化时,需要传入一个io.Reader类型的变量,这问题就来了,一个io.Reader类型的变量,一定是实现了Read方法了,那么为什么还需要装进bufio.Reader对象中呢?原来,bufio.Reader类中得Read方法,在读取字节流时,对传入的[]byte类型变量空间长度进行检查,如果传入变量的长度小于bufio.Reader初始化的容量,将会首先调用io.Reader自己的Read方法,将内容写入到bufio.Reader对象的buffer中,然后将值复制给传入的[]byte变量。这样做的好处是,在执行io.Reader的Read方法时,多读取一些字节,这样对于像文件操作就大有裨益。

4.第四个类os.File

这个类实现了io.Writer与io.Reader类,但是有点特殊的是,os.File的Read方法与Write均需要借助于系统层面的文件操作方法.总所周知,在文件读取时,Read与Write方法时没有缓存的,也就是你读几个字节,取决于你传入的变量容量是多少,如果容量为1,那么对于文件读取而言,就会很慢,所以将os.File的对象,传入到bufio.Reader对象中,这样可以在某些程度上提高效率,哪些时候呢?就是你在调用Read方法时,传入的变量容量太小时,会提高读取效率.但是bufio.Reader提供的Read方法不能保证每次读到的字符数一致,这个与其实现方式有关,但是不影响我们使用,只要确保收到EOF,再停止读取即可.

总结

在使用I/O操作时,bufio包提供了带buffer的方式读取I/O流,在操作文件读取,报文读取等上,可以在某种程度上提高效率,bufio中的类,并没有从底层实现Read与Write方法,只是限定了最小读取量.这个最小量就是bufio.Reader初始化长度.
bytes.Buffer提供的buffer十分强大,这个类不仅实现了io.Reader接口,还实现了io.Writer接口.所以bytes.Buffer的对象不仅可以读取,还可以追加写入,写入的过程中,容量还可以自动扩展,所以,功能十分强大.但是在使用时,要注意安全,bytes.Buffer会不断的扩大,扩大,最终还会panic.


有疑问加站长微信联系(非本文作者)

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK