likes
comments
collection
share

抗遗忘:Go bytes Buffer 笔记

作者站长头像
站长
· 阅读数 9

创建缓冲区

方法签名:

  • func bytes.NewBufferString(s string) *bytes.Buffer
  • func bytes.NewBuffer(buf []byte) *bytes.Buffer
package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf1 := bytes.NewBufferString("hello world")
	buf2 := bytes.NewBuffer([]byte("hello world"))
	buf3 := bytes.NewBuffer([]byte{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'})
	fmt.Println(buf1.String(), buf2.String(), buf3.String())
}

WriteXx 系列方法

用于将内容写入缓冲区的尾部,或者写入一个实现了 io.Writer 的结构体,这里只适合于 WriteTo 方法。

Write 写入 []byte

方法签名:func (b *bytes.Buffer) Write(p []byte) (n int, err error)

package main

import (
	"bytes"
	"fmt"
)

func main() {
	s := []byte(" world")
	buf := bytes.NewBufferString("hello")
	buf.Write(s)
	fmt.Println(buf.String())
}

WriteString 写入 string

方法签名:func (b *bytes.Buffer) WriteString(s string) (n int, err error)

package main

import (
	"bytes"
	"fmt"
)

func main() {
	s := " world"
	buf := bytes.NewBufferString("hello")
	buf.WriteString(s)
	fmt.Println(buf.String())
}

WriteByte 写入 byte

方法签名:func (b *bytes.Buffer) WriteByte(c byte) error

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var s byte = '?'
	buf := bytes.NewBufferString("hello")
	buf.WriteByte(s)
	fmt.Println(buf.String()) // Output: hello?
}

WriteRune 写入 rune

方法签名: func (b *bytes.Buffer) WriteRune(r rune) (n int, err error)

rune类型的主要作用是提供一种方便的方式来处理Unicode字符集中的字符,尤其是那些不能由一个字节表示的字符。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var s rune = '中'
	buf := bytes.NewBufferString("hello")
	buf.WriteRune(s)
	fmt.Println(buf.String()) // Output: hello中
}

WriteTo 写入 io.Writer

方法签名:func (b *bytes.Buffer) WriteTo(w io.Writer) (n int64, err error)

package main

import (
	"bytes"
	"fmt"
	"os"
)

func main() {
	file, _ := os.Create("test.txt")
	defer file.Close()
	buf := bytes.NewBufferString("Hello, world!")

	// Write the buffer to the file
	buf.WriteTo(file)

	// Alternatively, you can write the buffer to the file using the Write method
	file.Write(buf.Bytes())

	// Or you can use the Fprintf method to write the buffer to the file
	fmt.Fprintf(file, buf.String())

	fmt.Println("File written successfully")
}

ReadXx 系列方法

ReadXx 系列方法用于从 Buffer 中读取内容,也可以从实现了 io.Reader 的结构体中读取内容,仅适用于 ReadFrom 方法。

Read 读取 []byte

方法签名:func (b *bytes.Buffer) Read(p []byte) (n int, err error)

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	s1 := make([]byte, 3)
	n, _ := buf.Read(s1)
	fmt.Println(string(s1), buf.String(), n) // Output: Hel lo, world! 3

	s2 := make([]byte, 7)
	n2, _ := buf.Read(s2)
	fmt.Println(string(s2), buf.String(), n2) // Output: lo, wor ld! 7
}

ReadByte 读取 byte

方法签名:func (b *bytes.Buffer) ReadByte() (byte, error)

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	b, _ := buf.ReadByte()
	fmt.Printf("The first byte is: %c\n", b) // Output: The first byte is: H

	b2, _ := buf.ReadByte()
	fmt.Printf("The second byte is: %c\n", b2) // Output: The second byte is: e
}

ReadBytes / ReadString 按分隔符读取 []byte

方法签名:

  • func (b *bytes.Buffer) ReadBytes(delim byte) (line []byte, err error)
  • func (b *bytes.Buffer) ReadString(delim byte) (line string, err error)

ReadBytesReadString 功能一样,区别在于返回的一个是字节切片,一个是字符串。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	b, _ := buf.ReadBytes('o')
	// Output: 读取的内容是:Hello,剩下的内容是:, world!
	fmt.Printf("读取的内容是:%s,剩下的内容是:%s\n", b, buf.String())
	b2, _ := buf.ReadBytes('o')
	// Output: 读取的内容是:, wo,剩下的内容是:rld!
	fmt.Printf("读取的内容是:%s,剩下的内容是:%s", b2, buf.String())
}

ReadRune 读取 rune

方法签名:func (b *bytes.Buffer) ReadRune() (r rune, size int, err error)

package main

import (
	"bytes"
	"fmt"
	"reflect"
)

func main() {
	buf := bytes.NewBufferString("你好,世界")
	r, _, _ := buf.ReadRune()
	fmt.Printf("The first rune is: %c\n", r) // Output: The first rune is: 你

	r2, _, _ := buf.ReadRune()
	fmt.Printf("The second byte is: %c\n", r2) // Output: The second byte is: 好

	fmt.Println(isRune(r), isRune2(r2)) // Output: true true
}

func isRune(r rune) bool {
	return reflect.TypeOf(r) == reflect.TypeOf(rune(0))
}

func isRune2(v interface{}) bool {
	var isRune bool
	switch v.(type) {
	case rune:
		isRune = true
	default:
		isRune = false
	}
	return isRune
}

ReadFromio.Reader 中读取

方法签名:func (b *bytes.Buffer) ReadFrom(r io.Reader) (n int64, err error)

package main

import (
	"bytes"
	"fmt"
	"os"
)

func main() {
	file, _ := os.Open("test.txt")
	buf := bytes.NewBufferString("内容:")
	buf.ReadFrom(file)
	fmt.Println(buf.String()) // Output: 内容:Hello, world!
}

取消最近一次读取

使用 UnreadByte (其方法签名为:func (b *bytes.Buffer) UnreadByte() error)和 UnreadRune (基方法签名为:func (b *bytes.Buffer) UnreadRune() error)来取消最近一次成功读取的最后一个 byterune 内容。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	s1 := make([]byte, 3)
	buf.Read(s1)
	fmt.Println(buf.String()) // Output: lo, world!

	buf.UnreadByte()
	fmt.Println(buf.String()) // Output: llo, world!

	buf2 := bytes.NewBufferString("你好,世界")
	buf2.ReadRune()
	buf2.ReadRune()
	buf2.ReadRune()
	fmt.Println(buf2.String()) // Output: 世界
	buf2.UnreadRune()
	fmt.Println(buf2.String()) // Output: ,世界
}

内容截取

使用 Truncate(方法签名:func (b *bytes.Buffer) Truncate(n int))可以截取指定前 n 个字节数据。

使用 Next(方法签名:func (b *bytes.Buffer) Next(n int) []byte)相反,可以截取指定 n 个字节后面的数据,并返回前 n 个字节数据。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	buf.Truncate(3)
	fmt.Println(buf.String()) // Output: Hel
	buf2 := bytes.NewBufferString("Hello, world!")
	n := buf2.Next(3)
	fmt.Println(string(n))     // Output: Hel
	fmt.Println(buf2.String()) // Output: lo, world!
}

清空 Buffer

使用 Reset(方法签名:func (b *bytes.Buffer) Reset())来清空 Buffer。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("Hello, world!")
	buf.Truncate(3)
	fmt.Println(buf.String()) // Output: Hel
	buf.Reset()
	fmt.Println(buf.String()) // Output: 
}

容量控制

Buffer 的容量是自动扩容的,可以通过 Available(方法签名:func (b *bytes.Buffer) Available() int)来获取当前分配的剩余容量,使用 AvailableBuffer(方法签名:func (b *bytes.Buffer) AvailableBuffer() []byte)来获得可用的 Buffer,增加其内容后,再写入原始的 Buffer。

如果需要手动扩容也可以调用 Grow(方法签名:func (b *bytes.Buffer) Grow(n int))方法来指定要增加的容量。通过 Len 方法可以获取 Buffer 中内容长度,Cap 方法来获取 Buffer 大小。

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var buf bytes.Buffer
	fmt.Println(buf.Available(), buf.Len(), buf.Cap()) // 0 0 0
	buf.Write([]byte("Hello, world!"))
	fmt.Println(buf.Available(), buf.Len(), buf.Cap()) // 51 13 64
	buf.Grow(64)
	fmt.Println(buf.Available(), buf.Len(), buf.Cap()) // 115 13 128
}