Buffer 介绍
Buffer 是 bytes 包中的一个 type Buffer struct{…}
(是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用)
Buffer 就像一个集装箱容器,可以存东西,取东西(存取数据)
创建缓冲器
func main() { buf1 := bytes.NewBufferString("hello") buf2 := bytes.NewBuffer([]byte("hello")) buf3 := bytes.NewBuffer([]byte{'h','e','l','l','o'}) fmt.Printf("%v,%v,%v\n",buf1,buf2,buf3) fmt.Printf("%v,%v,%v\n",buf1.Bytes(),buf2.Bytes(),buf3.Bytes()) buf4 := bytes.NewBufferString("") buf5 := bytes.NewBuffer([]byte{}) fmt.Println(buf4.Bytes(),buf5.Bytes()) } 复制代码
输出
hello,hello,hello [104 101 108 108 111],[104 101 108 108 111],[104 101 108 108 111] [] [] 复制代码
写入到缓冲器
buffer在new的时候是空的,也是可以直接Write的
Write
func (b *Buffer) Write(p []byte) (n int,err error) 复制代码
func main() { s := []byte(" world") buf := bytes.NewBufferString("hello") fmt.Printf("%v,%v\n",buf.String(),buf.Bytes()) buf.Write(s) fmt.Printf("%v,%v\n",buf.String(),buf.Bytes()) } 复制代码
结果
hello,[104 101 108 108 111] hello world,[104 101 108 108 111 32 119 111 114 108 100] 复制代码
WriteString
func (b *Buffer) WriteString(s string)(n int,err error) 复制代码
func main() { s := " world" buf := bytes.NewBufferString("hello") fmt.Printf("%v,%v\n",buf.String(),buf.Bytes()) buf.WriteString(s) fmt.Printf("%v,%v\n",buf.String(),buf.Bytes()) } 复制代码
结果
hello,[104 101 108 108 111] hello world,[104 101 108 108 111 32 119 111 114 108 100] 复制代码
WriteByte
func (b *Buffer) WriteByte(c byte) error 复制代码
func main() { var s byte = '?' buf := bytes.NewBufferString("hello") fmt.Println(buf.Bytes()) buf.WriteByte(s) fmt.Println(buf.Bytes()) } 复制代码
WriteRune
func (b *Buffer) WriteRune(r Rune) (n int,err error) 复制代码
func main(){ var s rune = '好' buf := bytes.NewBufferString("hello") fmt.Println(buf.String()) buf.WriteRune(s) fmt.Println(buf.String()) } 复制代码
结果
22909 [104 101 108 108 111] [104 101 108 108 111 229 165 189] 复制代码
从缓冲器中写出
func main() { file,_ := os.Create("test.txt") buf := bytes.NewBufferString("hello world") buf.WriteTo(file) } 复制代码
读出缓冲器
Read
func (b *Buffer) Read(p []byte)(n int,err error) 复制代码
func main() { s1 := []byte("hello") buff :=bytes.NewBuffer(s1) s2 := []byte(" world") buff.Write(s2) fmt.Println(buff.String()) s3 := make([]byte,3) buff.Read(s3) fmt.Println(string(s3)) fmt.Println(buff.String()) buff.Read(s3) fmt.Println(string(s3)) fmt.Println(buff.String()) } 复制代码
ReadByte
返回缓冲器头部的第一个byte
func (b *Buffer) ReadByte() (c byte,err error) 复制代码
func main() { buf := bytes.NewBufferString("hello") fmt.Println(buf.String()) // hello b,_:= buf.ReadByte() fmt.Println(string(b)) //h fmt.Println(buf.String()) //ello } 复制代码
ReadRun
ReadRune方法,返回缓冲器头部的第一个rune
func (b *Buffer) ReadRune() (r rune,size int,err error) 复制代码
func main() { buf1 := bytes.NewBufferString("你好xuxiaofeng") fmt.Println(buf1.Bytes()) b1,n1,_ := buf1.ReadRune() fmt.Println(string(b1)) fmt.Println(n1) buf := bytes.NewBufferString("hello") fmt.Println(buf.String()) b,n,_:= buf.ReadRune() fmt.Println(n) fmt.Println(string(b)) fmt.Println(buf.String()) } 复制代码
为什么n==3,而n1==1呢?我们看下ReadRune 的源码
func (b *Buffer) ReadRune() (r rune, size int, err error) { if b.empty() { b.Reset() return 0, 0, io.EOF } c := b.buf[b.off] if c < utf8.RuneSelf { b.off++ b.lastRead = opReadRune1 return rune(c), 1, nil } r, n := utf8.DecodeRune(b.buf[b.off:]) b.off += n b.lastRead = readOp(n) return r, n, nil } 复制代码
ReadBytes
ReadBytes方法,需要一个byte作为分隔符,读的时候从缓冲器里找出第一个出现的分隔符,缓冲器头部开始到分隔符之间的byte返回。
func (b *Buffer) ReadBytes(delim byte) (line []byte,err error) 复制代码
func main() { var d byte = 'f' buf := bytes.NewBufferString("xuxiaofeng") fmt.Println(buf.String()) b,_ :=buf.ReadBytes(d) fmt.Println(string(b)) fmt.Println(buf.String()) } 复制代码
相当于有一个分隔符
ReadString
和readBytes方法类似
读入缓冲器
ReadFrom方法,从一个实现io.Reader接口的r,把r的内容读到缓冲器里,n返回读的数量
func (b *Buffer) ReadFrom(r io.Reader) (n int64,err error) 复制代码
func main(){ file, _ := os.Open("text.txt") buf := bytes.NewBufferString("bob ") buf.ReadFrom(file) fmt.Println(buf.String()) } 复制代码
从缓冲器取出
Next方法,返回前n个byte(slice),原缓冲器变
func (b *Buffer) Next(n int) []byte 复制代码
func main() { buf := bytes.NewBufferString("helloworld") fmt.Println(buf.String()) // helloworld b := buf.Next(2) fmt.Println(string(b)) // he } 复制代码
缓冲区原理介绍
go字节缓冲区底层以字节切片做存储,切片存在长度len与容量cap, 缓冲区写从长度len的位置开始写,当len>cap时,会自动扩容。缓冲区读会从内置标记off位置开始读(off始终记录读的起始位置),当off==len时,表明缓冲区已全部读完
并重置缓冲区(len=off=0),此外当将要内容长度+已写的长度(即len) <= cap/2时,缓冲区前移覆盖掉已读的内容(off=0,len-=off),从避免缓冲区不断扩容
func main() { byteSlice := make([]byte, 20) byteSlice[0] = 1 // 将缓冲区第一个字节置1 byteBuffer := bytes.NewBuffer(byteSlice) // 创建20字节缓冲区 len = 20 off = 0 c, _ := byteBuffer.ReadByte() // off+=1 fmt.Printf("len:%d, c=%d\n", byteBuffer.Len(), c) // len = 20 off =1 打印c=1 byteBuffer.Reset() // len = 0 off = 0 fmt.Printf("len:%d\n", byteBuffer.Len()) // 打印len=0 byteBuffer.Write([]byte("hello byte buffer")) // 写缓冲区 len+=17 fmt.Printf("len:%d\n", byteBuffer.Len()) // 打印len=17 byteBuffer.Next(4) // 跳过4个字节 off+=4 c, _ = byteBuffer.ReadByte() // 读第5个字节 off+=1 fmt.Printf("第5个字节:%d\n", c) // 打印:111(对应字母o) len=17 off=5 byteBuffer.Truncate(3) // 将未字节数置为3 len=off+3=8 off=5 fmt.Printf("len:%d\n", byteBuffer.Len()) // 打印len=3为未读字节数 上面len=8是底层切片长度 byteBuffer.WriteByte(96) // len+=1=9 将y改成A byteBuffer.Next(3) // len=9 off+=3=8 c, _ = byteBuffer.ReadByte() // off+=1=9 c=96 fmt.Printf("第9个字节:%d\n", c) // 打印:96 } 复制代码
欢迎关注我们的微信公众号,每天学习 Go 知识
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解
- 详解Openstack环境准备
- Java泛型详解
- iOS RunLoop 详解
- Raft协议详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。