文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

bytes.Buffer怎么在golang中使用

2023-06-14 20:21

关注

bytes.Buffer怎么在golang中使用?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

go适合做什么

go是golang的简称,而golang可以做服务器端开发,且golang很适合做日志处理、数据打包、虚拟机处理、数据库代理等工作。在网络编程方面,它还广泛应用于web应用、API应用等领域。

1 bytes.Buffer定义

bytes.Buffer提供可扩容的字节缓冲区,实质是对切片的封装;结构中包含一个64字节的小切片,避免小内存分配:

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.// The zero value for Buffer is an empty buffer ready to use.type Buffer struct { buf       []byte   // contents are the bytes buf[off : len(buf)] off       int      // read at &buf[off], write at &buf[len(buf)]--->指示读指针 bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation. lastRead  readOp   // last read operation, so that Unread* can work correctly.}

2 初始化bytes.Buffer的方法

1) var buf bytes.Buffer ->定义一个空的字节缓冲区

2) func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } -->将字节切片初始化为缓冲区

3) func NewBufferString(s string) *Buffer {return &Buffer{buf: []byte(s)}} -->将字符串初始化为缓冲区

3 提供的主要API函数

1)写字节流数据到缓冲区

// Write appends the contents of p to the buffer, growing the buffer as// needed. The return value n is the length of p; err is always nil. If the// buffer becomes too large, Write will panic with ErrTooLarge.func (b *Buffer) Write(p []byte) (n int, err error) { b.lastRead = opInvalid m := b.grow(len(p)) return copy(b.buf[m:], p), nil}

2)写字符串到缓冲区

// WriteString appends the contents of s to the buffer, growing the buffer as// needed. The return value n is the length of s; err is always nil. If the// buffer becomes too large, WriteString will panic with ErrTooLarge.func (b *Buffer) WriteString(s string) (n int, err error) { b.lastRead = opInvalid //返回写入的index m := b.grow(len(s)) return copy(b.buf[m:], s), nil}

3)从缓冲区中读取数据

// Read reads the next len(p) bytes from the buffer or until the buffer// is drained. The return value n is the number of bytes read. If the// buffer has no data to return, err is io.EOF (unless len(p) is zero);// otherwise it is nil.func (b *Buffer) Read(p []byte) (n int, err error) { b.lastRead = opInvalid if b.off >= len(b.buf) {  // Buffer is empty, reset to recover space.  b.Truncate(0)  if len(p) == 0 {   return  }  return 0, io.EOF } n = copy(p, b.buf[b.off:]) b.off += n if n > 0 {  b.lastRead = opRead } return}

4)从缓冲区中读取字符串,直到分隔符delim 位置

// ReadString reads until the first occurrence of delim in the input,// returning a string containing the data up to and including the delimiter.// If ReadString encounters an error before finding a delimiter,// it returns the data read before the error and the error itself (often io.EOF).// ReadString returns err != nil if and only if the returned data does not end// in delim.func (b *Buffer) ReadString(delim byte) (line string, err error) { slice, err := b.readSlice(delim) return string(slice), err}

5)将未被读取的字节数据返回

// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.// The slice is valid for use only until the next buffer modification (that is,// only until the next call to a method like Read, Write, Reset, or Truncate).// The slice aliases the buffer content at least until the next buffer modification,// so immediate changes to the slice will affect the result of future reads.func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }

6)将未被读取的字节数据以字符串形式返回

// String returns the contents of the unread portion of the buffer// as a string. If the Buffer is a nil pointer, it returns "<nil>".func (b *Buffer) String() string { if b == nil {  // Special case, useful in debugging.  return "<nil>" } return string(b.buf[b.off:])}

7)返回缓冲区当前容量

// Cap returns the capacity of the buffer's underlying byte slice, that is, the// total space allocated for the buffer's data.func (b *Buffer) Cap() int { return cap(b.buf) }

8)返回未被读取的字节数据大小

// Len returns the number of bytes of the unread portion of the buffer;// b.Len() == len(b.Bytes()).func (b *Buffer) Len() int { return len(b.buf) - b.off }

4 bytes.Buffer自动扩容机制

当向缓冲区写入数据时,首先会检查当前容量是否满足需求,如果不满足分三种情况处理:

1)当前内置缓冲区切片buf为空,且写入数据量小于bootstrap的大小(64字节),则bootstrap作为buf

2)当前未读数据长度+新写入数据长度小于等于缓冲区容量的1/2,则挪动数据(将未读的数据放到已读数据位置)

3)以上条件不满足,只能重新分配切片,容量设定为2*cap(b.buf) + n,即两倍原来的缓冲区容量+写入数据量大小

// grow grows the buffer to guarantee space for n more bytes.// It returns the index where bytes should be written.// If the buffer can't grow it will panic with ErrTooLarge.func (b *Buffer) grow(n int) int { m := b.Len() // If buffer is empty, reset to recover space. if m == 0 && b.off != 0 {  b.Truncate(0) } //如果需要的容量大于现在的容量---> if len(b.buf)+n > cap(b.buf) {  var buf []byte  //现有的预备64byte可以满足  if b.buf == nil && n <= len(b.bootstrap) {   buf = b.bootstrap[0:]   //实际需要的小于本身切片容量  } else if m+n <= cap(b.buf)/2 {   // We can slide things down instead of allocating a new   // slice. We only need m+n <= cap(b.buf) to slide, but   // we instead let capacity get twice as large so we   // don't spend all our time copying.   copy(b.buf[:], b.buf[b.off:])   buf = b.buf[:m]  } else {   // not enough space anywhere   //不够,那就分配2倍加n的容量   buf = makeSlice(2*cap(b.buf) + n)   copy(buf, b.buf[b.off:])  }  b.buf = buf  b.off = 0 } b.buf = b.buf[0 : b.off+m+n] return b.off + m}

5 bytes.Buffer的局限

bytes.Buffer提供了对切片的初步封装,但也没做太多的事;对于已读的数据无法操作。

补充:Golang bytes.Buffer 用法精述

1.简介

bytes.Buffer 是 Golang 标准库中的缓冲区,具有读写方法和可变大小的字节存储功能。缓冲区的零值是一个待使用的空缓冲区。

定义如下:

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.}

注意要点:

(1)从 bytes.Buffer 读取数据后,被成功读取的数据仍保留在原缓冲区,只是无法被使用,因为缓冲区的可见数据从偏移 off 开始,即buf[off : len(buf)]。

2.常用方法

(1)声明一个 Buffer

var b bytes.Buffer           //直接定义一个Buffer变量,不用初始化,可以直接使用b := new(bytes.Buffer)       //使用New返回Buffer变量b := bytes.NewBuffer(s []byte)     //从一个[]byte切片,构造一个Bufferb := bytes.NewBufferString(s string) //从一个string变量,构造一个Buffer

(2)往 Buffer 中写入数据

b.Write(d []byte) (n int, err error)      //将切片d写入Buffer尾部b.WriteString(s string) (n int, err error)   //将字符串s写入Buffer尾部b.WriteByte(c byte) error        //将字符c写入Buffer尾部b.WriteRune(r rune) (n int, err error)      //将一个rune类型的数据放到缓冲区的尾部b.ReadFrom(r io.Reader) (n int64, err error) //从实现了io.Reader接口的可读取对象写入Buffer尾部

(3)从 Buffer 中读取数据

//读取 n 个字节数据并返回,如果 buffer 不足 n 字节,则读取全部b.Next(n int) []byte//一次读取 len(p) 个 byte 到 p 中,每次读取新的内容将覆盖p中原来的内容。成功返回实际读取的字节数,off 向后偏移 n,buffer 没有数据返回错误 io.EOFb.Read(p []byte) (n int, err error)//读取第一个byte并返回,off 向后偏移 nb.ReadByte() (byte, error)//读取第一个 UTF8 编码的字符并返回该字符和该字符的字节数,b的第1个rune被拿掉。如果buffer为空,返回错误 io.EOF,如果不是UTF8编码的字符,则消费一个字节,返回 (U+FFFD,1,nil)b.ReadRune() (r rune, size int, err error)//读取缓冲区第一个分隔符前面的内容以及分隔符并返回,缓冲区会清空读取的内容。如果没有发现分隔符,则返回读取的内容并返回错误io.EOFb.ReadBytes(delimiter byte) (line []byte, err error)//读取缓冲区第一个分隔符前面的内容以及分隔符并作为字符串返回,缓冲区会清空读取的内容。如果没有发现分隔符,则返回读取的内容并返回错误 io.EOFb.ReadString(delimiter byte) (line string, err error)//将 Buffer 中的内容输出到实现了 io.Writer 接口的可写入对象中,成功返回写入的字节数,失败返回错误b.WriteTo(w io.Writer) (n int64, err error)

(4)其它操作

b.Bytes() []byte  //返回字节切片b.Cap() int    //返回 buffer 内部字节切片的容量b.Grow(n int)   //为 buffer 内部字节切片的容量增加 n 字节b.Len() int    //返回缓冲区数据长度,等于 len(b.Bytes())b.Reset()     //清空数据b.String() string  //字符串化b.Truncate(n int)  //丢弃缓冲区中除前n个未读字节以外的所有字节。如果 n 为负数或大于缓冲区长度,则引发 panicb.UnreadByte() error //将最后一次读取操作中被成功读取的字节设为未被读取的状态,即将已读取的偏移 off 减 1b.UnreadRune() error //将最后一次 ReadRune() 读取操作返回的 UTF8 字符 rune设为未被读取的状态,即将已读取的偏移 off 减去 字符 rune 的字节数

3.使用示例

(1)从文件 test.txt 中读取全部内容追加到 buffer 尾部

test.txt 的内容为:

My name is dablelv

具体实现:

package mainimport ( "os" "fmt" "bytes")func main() {    file, _ := os.Open("./test.txt")        buf := bytes.NewBufferString("Hello world ")        buf.ReadFrom(file)              //将text.txt内容追加到缓冲器的尾部        fmt.Println(buf.String())}

编译运行输出:

Hello world My name is dablelv

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯