Go 语言标准库 bytes ,实现了对字节数组的各种操作。 It is analogous to the facilities of strings package. (它和string 标准包提供的功能类似)
提供的功能如下;
- 字节切片 处理函数
- 基本处理函数
- 字节切片比较函数
- 前后缀检查函数
- 字节切片位置索引函数
- 分割函数
- 大小写处理函数
- 子字节切片处理函数
Buffer
对象Reader
对象
字节切片处理函数
基本处理函数 共七个
- Contains() 返回是否包含子切片
- Count() 子切片非重叠实例的数量
- Map() 函数,将byte 转化为Unicode,然后进行替换
- Repeat() 将切片复制count此,返回这个新的切片
- Replace() 将切片中的一部分 替换为另外的一部分
- Runes() 将 S 转化为对应的 UTF-8 编码的字节序列,并且返回对应的Unicode 切片
- Join() 函数,将子字节切片连接到一起。
func Contains(b, subslice []byte) bool
func Contains(b, subslice [] byte) bool
检查字节切片 b ,是否包含子字节切片 subslice
package main
import (
"bytes"
"fmt"
)
func main() {
// 这里不能写成 b := []byte{"Golang"},这里是利用类型转换。
b := []byte("Golang")
subslice1 := []byte("go")
subslice2 := []byte("Go")
fmt.Println(bytes.Contains(b, subslice1))
fmt.Println(bytes.Contains(b, subslice2))
}
Counts(s, spe[ []byte) int
func Count(s, sep []byte) int
计算子字节切片 sep 在字节切片 s 中出现的非重叠实例的数量。
package main
import (
"bytes"
"fmt"
)
func main() {
s := []byte("banana")
sep1 := []byte("ban")
sep2 := []byte("na")
sep3 := []byte("a")
fmt.Println(bytes.Count(s, sep1))
fmt.Println(bytes.Count(s, sep2))
fmt.Println(bytes.Count(s, sep3))
}
func Map(mapping func(r rune) rune, s []byte) []byte
Map函数:首先将 s 转化为 UTF-8编码的字符序列,然后使用 mapping 将每个Unicode字符映射为对应的字符,最后将结果保存在一个新的字节切片中。
package main
import (
"bytes"
"fmt"
)
func main() {
s := []byte("同学们,上午好")
m := func(r rune) rune {
if r == '上' {
r = '下'
}
return r
}
fmt.Println(string(s))
fmt.Println(string(bytes.Map(m, s)))
}
func Repeat(b []byte, count int) []byte
func Replace(s, old, new []byte, n int) []byte
返回字节切片 S 的一个副本, 并且将前n个不重叠的子切片 old 替换为 new,如果n < 0 那么不限制替换的数量
package main
import (
"bytes"
"fmt"
)
func main() {
s := []byte("google")
old := []byte("o")
//这里 new 是一个字节切片,不是关键字了
new := []byte("oo")
n := 1
fmt.Println(string(bytes.Replace(s, old, new, n)))
fmt.Println(string(bytes.Replace(s, old, new, -1)))
}
func Runes(b []byte) []rune
将字节切片 转化为对应的 UTF-8编码的字节序列,并且返回对应的 Unicode 切片。
package main
import (
"bytes"
"fmt"
)
//每个 rune 变量占据 4个字节,等价于 int32
//每个 byte 变量占据1个字节,等价于int8
func main() {
s := []byte("中华人民共和国")
r := bytes.Runes(s)
fmt.Println(string(s), len(s)) //字节切片的长度
fmt.Println(string(r), len(r)) // rune 切片的长度
}
func Join(s [][]byte, sep []byte) []byte
用字节切片 sep 吧 s中的每个字节切片连接成一个,并且返回.
package main
import (
"bytes"
"fmt"
)
func main() {
// 字节切片 的每个元素,依旧是字节切片。
s := [][]byte{
[]byte("你好"),
[]byte("世界"), //这里的逗号,必不可少
}
sep := []byte(",")
fmt.Println(string(bytes.Join(s, sep)))
var a = []int{1,
2,
3,
5, //这里的逗号,也必不可少
}
fmt.Println(a)
var b = []int{1, 2, 3, 4, 5} //这里最后一个元素不需要逗号
fmt.Println(b)
}
字节切片比较函数
func Compare(a, b[]byte) int
: 返回整数:1, 0 ,-1
func Equal(a, b []byte) bool
: 返回true or false
func EqualFold(a, b []byte) bool
: 忽略大小写:返回 true or false
package main
import (
"bytes"
"fmt"
)
func main() {
a := []byte("abc")
b := []byte("ABC")
s := []byte("GOLANG")
t := []byte("golang")
fmt.Println(bytes.Compare(a, b))
fmt.Println(bytes.Equal(a, b))
fmt.Println(bytes.EqualFold(s, t))
}
输出为:
1
false
true
字节切片 前后缀 检查函数
func HasPreifx(s, prefix []byte) bool
func HasSuffix(s, suffix []byte) bool
字节切片 位置索引函数
func Index(s, sep []byte) int
返回字节切片在s中第一次出现的位置(索引从0 开始),不存在返回-1.func IndexAny(s []byte, chars string)
将字节切片解释为 UTF-8的字符,返回 chars 中任何一个字符在s中 第一次出现的位置。(chars 中保存的是 Unicode字符集)func IndexByte(s []byte, c byte) int
func IndexFunc(s []byte, f func(r rune)bool) int
将 s 解释成 UTF-8字节序列, 并且返回第一个使得 f(c) = ture的字符 c的索引位置。func IndexRue(s []byte, r rune)
func LastIndex(s ,sep []byte) int
func LastIndexAny (s []byte, chars string) int
func LastIndexFunc(s []byte, f func(r rune) bool) int
字节切片 分割函数
func Fields(s []byte) [][]byte
将字节切片 s 按照 一个或者连续多个空白字符 分割成 多个字节切片。如果 s 只包含空白字符,则返回 空字节切片。
package main
import (
"bytes"
"fmt"
)
func main() {
s := []byte(" I'm a student. ")
for _, f := range bytes.Fields(s) {
fmt.Printf("%q ", f)
}
s1 := []byte(" ")
s2 := bytes.Fields(s1)
fmt.Println(len(s2), s2 == nil)
}
程序输出如下:
"I'm" "a" "student." 0 false
func FieldsFunc(s []byte, f func(r rune) bool) [][]byte
, 首先将s 解释成 Unicode 字符序列,然后用函数 f 进行测试。func Split(s, sep []byte) [][]byte
按照字节序列 sep 进行分割func SplitN(s, sep []byte, n int) [][]byte
按照字节序列 sep 进行分割,并且 可以设置 分割成的字节切片的个数,n == -1表示返回所有的子切片。func SplitAfter(s, sep[] byte) [][]byte
,这里是不舍弃 sep,而是保留sep。func SplitAfterN(s, sep[] byte, int n) [][]byte
和上次是一样的。字节切片大小写处理函数
func Title(s []byte) []byte
返回s的一个副本,并且将S中每个单词的首字母转化成 Unicode大写字符。func ToTitle(s []byte) []byte
将其中的所有Unicode字符转化成大写。func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte
func ToLower(s []byte) []byte
func ToLowerSpeical(_case unicode.SpecialCase, s[]byte) []byte
func ToUpper(s []byte) []byte
func ToUpperSpecial (_case unicode.SpecialCase, s []byte) []byte
子字节 切片 处理函数
将 一个 字节切片截端,然后返回新的字节切片
func Trim(s []byte, cutset string) []byte
func TrimFunc(s []byte, f func(r rune) bool) []byte
func TrimLeft(s []byte, cutset string) []byte
func TrimLeftFunc(s []byte, f func(r rune) bool) []byte
func TrimRight(s []byte, cutset string) []byte
func TrimRightFunc (s []byte, f func(r rune) bool) []byte
func TrimPrefix(s, prefix []byte) []byte
func TrimSuffix(s, suffix []byte) []byte
func TrimSpace(s []byte) []byte
Buffer and Reader
现在需要对字节切片进行读写: 比如说,不停地向字节切片中 写入字符串, 从字节切片中读取字符串等等操作。
于是我们有了 Buffer and Reader.
bytes.Buffer
Buffer 是 bytes 包中的一个 type Buffer struct{…}
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. (是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用)
在我看来: Buffer 是一种抽象,想想成一个不限容量蓄水池,你可以向其中加水,同时也可以向其中取出水。(存入数据,和取数据)
- 创建 一个 Buffer (其实底层就是一个 []byte, 字节切片)
- 向其中写入数据 (Write mtheods)
- 从其中读取数据 (Write methods)
创建 Buffer
var b bytes.Buffer //直接定义一个 Buffer 变量,而不用初始化
b.Writer([]byte("Hello ")) // 可以直接使用
b1 := new(bytes.Buffer) //直接使用 new 初始化,可以直接使用
// 其它两种定义方式
func NewBuffer(buf []byte) *Buffer
func NewBufferString(s string) *Buffer
Buffer 基本函数
func (b *Buffer) Bytes() []byte
返回 没有读取的 内容
func (b *Buffer) Grow() (n int)
增加 buffer 的容量
func (b *Buffer) Len() int
返回没有读取的内容的长度
func (b *Buffer) Next(n int) []byte
返回没有读取的 n个字节,副作用,就像采用了Read 方法进行了读一样。
向 Buffer 中读取数据
func (*Buffer) Read(p []byte) (n int, err error)
从 Buffer 从读取 len(p) 的数据,直到 Buffer 没有数据可以读取。 返回值是读取数据的字节数。 如果没有数据可以读取,那么err 的值是 io.EOF
func (*Buffer) ReadByte() (c byte, err error)
func (*Buffer) ReadBytes(delim byte) (line []byte, err error)
遇到第一个 delim 的时候,将数据返回。
func (*Buffer)ReadRune() (r rune, err error)
func (*Buffer) ReadString(delim byte) (line string, err error)
func (*Buffer) Reset()
将数据清空,没有数据可读
func (*Buffer) String() string
将未读取的数据返回成 string
func (*Buffer) Truncate(n int)
在Buffer中保留 n个未读的数据。
func (*Buffer) UnreadByte() error
func (*Buffer) UnreadRune() error
小心返回错误。
func (*Buffer) ReadFrom( r o.Reader) (n int64, err error)
从 IO 接口 对象 r中读取数据,并且写入到 buffer中,知道 r.Read 返回 io.EOF。 (当然)
向 Buffer 中写入数据
func (b * Buffer) Write(p []byte) (n int, err error)
把字节切片 p 写入到buffer中去。
func (b *Buffer) WriteByte(c byte) error
func (b *Buffer) WriteRune(c byte) error
func (b *Buffer) WriteString(s string) (n int, err error)
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)
将Buffer 中的数据写入到 I/O对象 writer 中去,知道数据为空,或者遇到错误。
bytes.Reader
Reader 是另外一个可以对切片进行操作的方法,但是 Reader只可以对数据进行 读取操作,不从向切片中写入数据。Reader 支持对切片进行Seek()
定位 操作。
总结
说明了一下几点:
1. []byte 字节切片是 golang中的(最)重要的工具,好好利用字节切片
2. 掌握好对字节切片进行操作的工具。 (有好的工具很重要)
3. 多多写程序,才可以有收获
有疑问加站长微信联系(非本文作者)