11

Golang 语言标准库 bytes 包怎么使用?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzA4Mjc1NTMyOQ%3D%3D&%3Bmid=2247484410&%3Bidx=1&%3Bsn=e50b07f7adf7ac0c5f6d0496509d34fa
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.

01 

介绍

Golang 语言中内置了两种字符类型,分别是 byte 的字节类类型,和 rune 的字符类类型。其中 byte 是 uint8 的别名,表示 ASCII 码的一个字符,占用 1 个字节,rune 是 int32 的别名,表示 UTF-8 字符,占用 4 个字节。

[]byte 表示字节切片,因为字符串也可以表示为字节切片,所以 bytes 包的函数和 strings 包的函数比较相似。

本文主要讲解 bytes(byte slice)包的使用方法,并不会涉及比较 string 和 []byte 相关的内容,比如二者的底层实现、区别和相互转换等。

02 

函数

bytes 包提供了很多操作字节切片的函数,大致分为如下几类:

  • 比较

  • 包含

  • 索引

  • 分割

  • 转换

  • 清除

限于篇幅,我们无法将所有函数都介绍,本文我们在每个分类中挑选比较常用的函数来介绍。

比较

  • func Compare(a, b []byte) int Compare 函数用于按照字典序比较两个字节切片的大小,返回值有 3 种情况,分别是:

    • 返回 0,代表 a == b

    • 返回 -1,代表 a < b

    • 返回 +1,代表 a > b

注意:nil 作为参数,表示一个空切片。

  • func Equal(a, b []byte) bool Equal 函数用于比较两个字节切片的长度和字节是否都相等,返回值是一个 bool 类型。

注意:nil 作为函数,表示一个空切片。

包含

  • func Contains(b, subslice []byte) bool Contains 函数用于判断 subslice 子字节切片是否包含在 b 字节切片,返回值是一个 bool 类型。

  • func Count(s, sep []byte) int Count 函数用于统计 sep 字节切片在 s 字节切片中非重叠实例数。

注意:如果 sep 是一个空切片,返回值是 s 切片长度加 1。

  • func HasPrefix(s, prefix []byte) bool HasPrefix 函数用于判断字节切片 s 是否以 prefix 开头,返回值是一个 bool 类型。

  • func HasSuffix(s, suffix []byte) bool HasSuffix 函数用于判断字节切片 s 是否以 suffix 结尾,返回值是一个 bool 类型。

索引

  • func Index(s, sep []byte) int Index 函数用于查找 sep 在 s 中第一次出现的索引下标,如果没有则返回 -1。

  • func LastIndex(s, sep []byte) int LastIndex 函数用于查找 sep 在 s 中最后一次出现的索引下标,如果没有则返回 -1。

分割

  • func Split(s, sep []byte) [][]byte Split 函数用于将 sep 作为分割符,将 s 分割,返回拆分之后的字节切片。

注意:如果 sep 为空,将按照每个字节进行拆分。

  • func SplitN(s, sep []byte, n int) [][]byte SplitN 函数用于将 sep 作为分割符,将 s 分割 n 份,返回拆分之后的字节切片。

转换

  • func ToLower(s []byte) []byte ToLower 函数用于将字节切片所有字节全部转换为小写字母,返回该字节切片的一个副本。

  • func ToUpper(s []byte) []byte ToUpper 函数用于将字节切片所有字节全部转换为大小字母,返回该字节切片的一个副本。

清除

  • func Trim(s []byte, cutset string) []byte Trim 函数返回清除 s 中开头和结尾存在的 cutset 之后的一个子切片。

  • func TrimLeft(s []byte, cutset string) []byte TrimLeft 函数返回清除 s 中开头存在的 cutset 之后的一个子切片。

  • func TrimRight(s []byte, cutset string) []byte TrimRight 函数返回清除 s 中结尾存在的 cutset 之后的一个子切片。

  • func TrimSpace(s []byte) []byte TrimSpace 函数返回清除 s 中开头和结尾存在的  \t\n\r 之后的一个子切片。

03

Buffer

Buffer 定义了一个可读写和可变大小的字节缓冲区,源码如下:

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

阅读源码,我们发现 Buffer 结构中的字段 buf 是 []byte 类型,用于存储数据,字段 off 是 int 类型,用于记录读写位置。

创建 Buffer

创建 BUffer 有以下三种方式:

  1. var b bytes.Buffer

  2. func NewBuffer(buf []byte) *Buffer 使用 NewBuffer 函数

  3. func NewBufferString(s string) *Buffer 使用 NewBufferString 函数

注意:三种方式的区别是 2 和 3 相比 1,可以在创建 Buffer 的同时初始化数据,其中 2 和 3 的区别是创建 Buffer 时,用于初始化的数据类型不同。

Buffer 方法

Buffer 结构提供了很多方法,限于篇幅,本文也是只介绍一些比较常用的。

  • func (b *Buffer) Len() int Len 方法用于获取缓冲区未读的字节数。

  • func (b *Buffer) String() string String 方法用于将缓冲区未读数据作为字符串返回。

  • func (b *Buffer) Truncate(n int) Truncate 方法用于截断缓冲区前 n 个未读字节之后所有字节。

  • func (b *Buffer) Reset() Reset 方法用于将缓冲区置空。

  • func (b *Buffer) Grow(n int) Grow 方法用于增加 n 字节的缓冲区的容量。

  • func (b *Buffer) Read(p []byte) (n int, err error) Read 方法用于读取缓冲区 len(p) 的字节。

  • func (b *Buffer) Next(n int) []byte Next 方法用于读取缓冲区下一个 n 字节的数据。

注意:Next 方法和 Read 方法的区别是,Next 是对当前缓冲区直接进行 slice 操作并返回结果,Read 是从当前缓冲区拷贝数据到新的 slice。

  • func (b *Buffer) Write(p []byte) (n int, err error) Write 方法用于将 p 追加到当前缓冲区。

  • func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) WriteTo 方法用于将缓冲区中的数据写入到一个 writer 中。

04 

Reader

Reader 实现了 io.Reader, io.ReaderAt, io.WriterTo, io.Seeker, io.ByteScanner, io.RuneScanner 接口。可以读取  []byte 。与 Buffer 可读写不同,Reader 是只读和支持查找。下面是 Reader 结构的源码:

type Reader struct {
s []byte
i int64 // current reading index
prevRune int // index of previous rune; or < 0
}

Reader 结构中的字段 s 是一个 []byte 类型,用于存储数据,字段 i 是一个 int64 类型,用于存储当前读取的索引位置。

创建 Reader

func NewReader(b []byte) *Reader

使用 NewReader 函数可以创建一个读取 b 的 Reader。

Reader 方法

Reader 也提供了很多方法,我们也将只介绍一些常用的方法。

  • func (r *Reader) Len() int Len 方法返回未读字节数。

  • func (r *Reader) Size() int64 Size 方法返回数据的总长度。

  • func (r *Reader) Reset(b []byte) Reset 方法将数据重置为 b。

  • func (r *Reader) Read(b []byte) (n int, err error) Read 方法实现了  io.Reader 接口。
  • func (r *Reader) WriteTo(w io.Writer) (n int64, err error) WriteTo 方法实现了  io.WriterTo 接口。

05 

总结

本文介绍了 Golang 语言标准库的 bytes 包的函数和两个结构,Buffer 和 Reader,以及它们各自的方法。通过阅读本文,读者可以了解 bytes 包的使用方法和部分底层实现。

bytes 包提供的函数不止文中介绍的这些,感兴趣的读者,建议阅读官方文档了解文中未被提及的函数。

关注微信公众号,加入读者微信群

发送关键字「资料」,免费获取 Go 语言学习资料。

fEBBJ3f.png!mobile

推荐阅读:

再见 2020,你好 2021

Golang 语言怎么使用 gomail 库发送邮件?

每位 Gopher 都应该了解的 Golang 语言的垃圾回收算法

Golang 语言的标准库 log 包怎么使用?

Golang 语言三方库 lumberjack 日志切割组件怎么使用?

Golang语言之字符串操作

参考资料:

https://golang.org/pkg/bytes/

:arrow_down:更多精彩内容,请点击「 阅读原文


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK