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

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

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 包提供的函数不止文中介绍的这些,感兴趣的读者,建议阅读官方文档了解文中未被提及的函数。





目录
相关文章
|
4月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
160 4
Golang语言之管道channel快速入门篇
|
4月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
133 3
Golang语言之gRPC程序设计示例
|
2月前
|
JSON Go 开发者
go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。
52 4
|
2月前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
4月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
87 3
Golang语言之Prometheus的日志模块使用案例
|
3月前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
57 0
|
4月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
80 4
Golang语言文件操作快速入门篇
|
4月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
108 4
|
4月前
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
62 3
|
4月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
116 4
Golang语言goroutine协程篇