Go bytes.Buffer 介绍
bytes.Buffer 一个我们经常使用的变长的byte buffer,它提供了对byte的读写操作。
类型组成
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
lastRead readOp // last read operation, so that Unread* can work correctly.
}
- buf 作为缓冲的内容,是个byte slice,读出来的内容就是buf[off:len(buf)],关注slice的len、cap。
- off 读取的当前偏移量,读buf时从buf[off]开始,写buf时从buf[len(buf)] 处,这个对理解bytes.Buffer尤其重要。
- lastRead 这个元素的作用主要就是为了撤销操作使用,后边会举例
读写方法
可以从go doc bytes.Buffer
中查看对外暴露的api,也比较好理解。都是针对这个Buffer的读、写操作。 重点还是在于理解Buffer中的off变化。
初始化
通常我们直接new一个或者声明一个变量就ok,默认
var bf bytes.Buffer
或者
var bf = new(bytes.Buffer)
写缓冲区
向缓冲区写内容时,涉及到底层byte slice的增长grow,默认最小容量是64字节。
grow基本策略:cap够长,还用自身底层buf;否则就分配一个新的够长的slice,然后copy过去。(够长指的 n <= c/2-m,m是Buffer的长,len(buf)-off)
var bf bytes.Buffer
// 写字符串进去
bf.Write([]byte("xxx"))
bf.WriteString("yyy")
// 写一个字符字节
bf.WriteByte('1')
bf.WriteRune('好')
// len和cap
fmt.Println(bf.Len(), bf.Cap())
// 打印
fmt.Println(bf.String(), bf.Bytes())
读缓冲区
从缓冲区里读,涉及到off的位移变动,长度也随之变化。
var bf bytes.Buffer
bf.WriteString("abcdefg")
fmt.Println(bf.Len(), bf.Cap()) // 7 64
var r = make([]byte, 5)
// 读到r中,读取r的长度或者把bf读完
n, err := bf.Read(r)
fmt.Println(n, err, string(r)) // 5 <nil> abcde
fmt.Println(bf.Len()) // 2
c, _ := bf.ReadByte()
fmt.Println(string(c), bf.Len()) // f 1
bf.Reset() // 重置 归0
bf.WriteString("abc=123=0")
// 读到第一个字节=结束,返回
l, _ := bf.ReadString('=')
fmt.Println(l, bf.Len()) // abc= 5
// 撤销一个字节的读, off--
bf.UnreadByte()
fmt.Println(bf.Len()) // 变回 6
// 读出来一个字节
b, _ := bf.ReadByte()
fmt.Println(string(b), bf.Len()) // = 5
连接Reader、Writer
var bf bytes.Buffer
// 从Reader中读取到bf中,读一个文件直到EOF
f, _ := os.Open("a.dat")
_, _= bf.ReadFrom(f)
fmt.Println(bf.String()) // 文件内容
// bf数据写到Writer
bf.WriteTo(os.Stdout) // 标准输出打印文件内容
总结
bytes.Buffer提供了简单易用的字节缓冲区及其读写方法,重点在于读写过程中底层的slice长度、容量变化,和读取位置off的变化,理解好有助于我们日常开发使用。
API附录
func NewBuffer(buf []byte) *Buffer
func NewBufferString(s string) *Buffer
func (b *Buffer) Bytes() []byte
func (b *Buffer) Cap() int
func (b *Buffer) Grow(n int)
func (b *Buffer) Len() int
func (b *Buffer) Next(n int) []byte
func (b *Buffer) Read(p []byte) (n int, err error)
func (b *Buffer) ReadByte() (byte, error)
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error)
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error)
func (b *Buffer) ReadRune() (r rune, size int, err error)
func (b *Buffer) ReadString(delim byte) (line string, err error)
func (b *Buffer) Reset()
func (b *Buffer) String() string
func (b *Buffer) Truncate(n int)
func (b *Buffer) UnreadByte() error
func (b *Buffer) UnreadRune() error
func (b *Buffer) Write(p []byte) (n int, err error)
func (b *Buffer) WriteByte(c byte) error
func (b *Buffer) WriteRune(r rune) (n int, err error)
func (b *Buffer) WriteString(s string) (n int, err error)
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)