简介

bytes包提供了对字节切片进行读写操作的一系列函数,字节切片处理的函数比较多分为基本处理函数、比较函数、后缀检查函数、索引函数、分割函数、大小写处理函数和子切片处理函数等。

[]byte参数(引用类型,函数中修改会改变外部变量)
一 相关函数

1.1 转换

func ToUpper(s []byte) []bytefunc ToLower(s []byte) []bytefunc ToTitle(s []byte) []bytefunc ToUpperSpecial(_case unicode.SpecialCase, s []byte) []bytefunc ToLowerSpecial(_case unicode.SpecialCase, s []byte) []bytefunc ToTitleSpecial(_case unicode.SpecialCase, s []byte) []bytefunc Title(s []byte) []byte

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var b = []byte("seafood") //强制类型转换

	a := bytes.ToUpper(b)
	fmt.Println(a, b) 

	c := b[0:4]
	c[0] = 'A'
	fmt.Println(c, b)
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
[83 69 65 70 79 79 68] [115 101 97 102 111 111 100]
[65 101 97 102] [65 101 97 102 111 111 100]

[Done] exited with code=0 in 1.023 seconds

可以看出函数不会修改原引用值类型。

1.2 比较

func Compare(a, b []byte) intfunc Equal(a, b []byte) boolfunc EqualFold(s, t []byte) bool

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	s1 := "Φφϕ kKK"
	s2 := "ϕΦφ KkK"

	// 看看 s1 里面是什么
	for _, c := range s1 {
		fmt.Printf("%-5x", c)
	}
	fmt.Println()
	// 看看 s2 里面是什么
	for _, c := range s2 {
		fmt.Printf("%-5x", c)
	}
	fmt.Println()
	// 看看 s1 和 s2 是否相似
	fmt.Println(bytes.EqualFold([]byte(s1), []byte(s2)))
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
3a6  3c6  3d5  20   6b   4b   212a 
3d5  3a6  3c6  20   212a 6b   4b   
true

[Done] exited with code=0 in 0.978 seconds

1.3 清理

func Trim(s []byte, cutset string) []bytefunc TrimLeft(s []byte, cutset string) []bytefunc TrimRight(s []byte, cutset string) []bytefunc TrimFunc(s []byte, f func(r rune) bool) []bytefunc TrimLeftFunc(s []byte, f func(r rune) bool) []bytefunc TrimRightFunc(s []byte, f func(r rune) bool) []bytefunc TrimSpace(s []byte) []bytefunc TrimPrefix(s, prefix []byte) []bytefunc TrimSuffix(s, suffix []byte) []byte

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	bs := [][]byte{ //[][]byte 字节切片 二维数组
		[]byte("Hello World !"),
		[]byte("Hello 世界!"),
		[]byte("hello golang ."),
	}

	f := func(r rune) bool {
		return bytes.ContainsRune([]byte("!!. "), r) //判断r字符是否包含在"!!. "内
	}

	for _, b := range bs { //range bs  取得下标和[]byte
		fmt.Printf("去掉两边: %q\n", bytes.TrimFunc(b, f)) //去掉两边满足函数的字符
	}

	for _, b := range bs {
		fmt.Printf("去掉前缀: %q\n", bytes.TrimPrefix(b, []byte("Hello "))) //去掉前缀
	}
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
去掉两边: "Hello World"
去掉两边: "Hello 世界"
去掉两边: "hello golang"
去掉前缀: "World !"
去掉前缀: "世界!"
去掉前缀: "hello golang ."

[Done] exited with code=0 in 0.925 seconds

1.4 拆合

func Split(s, sep []byte) [][]bytefunc SplitN(s, sep []byte, n int) [][]bytefunc SplitAfter(s, sep []byte) [][]bytefunc SplitAfterN(s, sep []byte, n int) [][]bytefunc Fields(s []byte) [][]bytefunc FieldsFunc(s []byte, f func(rune) bool) [][]bytefunc Join(s [][]byte, sep []byte) []bytefunc Repeat(b []byte, count int) []bytec

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	b := []byte("  Hello   World !  ")
	fmt.Printf("b: %q\n", b)
	fmt.Printf("%q\n", bytes.Split(b, []byte{' '}))

	fmt.Printf("%q\n", bytes.Fields(b))

	f := func(r rune) bool {
		return bytes.ContainsRune([]byte(" !"), r)
	}
	fmt.Printf("%q\n", bytes.FieldsFunc(b, f))
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
b: "  Hello   World !  "
["" "" "Hello" "" "" "World" "!" "" ""]
["Hello" "World" "!"]
["Hello" "World"]

[Done] exited with code=0 in 1.032 seconds

1.5 字串

func HasPrefix(s, prefix []byte) boolfunc HasSuffix(s, suffix []byte) boolfunc Contains(b, subslice []byte) boolfunc ContainsRune(b []byte, r rune) boolfunc ContainsAny(b []byte, chars string) boolfunc Index(s, sep []byte) intfunc IndexByte(s []byte, c byte) intfunc IndexRune(s []byte, r rune) intfunc IndexAny(s []byte, chars string) intfunc IndexFunc(s []byte, f func(r rune) bool) intfunc LastIndex(s, sep []byte) intfunc LastIndexByte(s []byte, c byte) intfunc LastIndexAny(s []byte, chars string) intfunc LastIndexFunc(s []byte, f func(r rune) bool) intfunc Count(s, sep []byte) int

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	b := []byte("hello golang") //字符串强转为byte切片
	sublice1 := []byte("hello")
	sublice2 := []byte("Hello")
	fmt.Println(bytes.Contains(b, sublice1)) //true
	fmt.Println(bytes.Contains(b, sublice2)) //false

	s := []byte("hellooooooooo")
	sep1 := []byte("h")
	sep2 := []byte("l")
	sep3 := []byte("o")
	fmt.Println(bytes.Count(s, sep1)) //1
	fmt.Println(bytes.Count(s, sep2)) //2
	fmt.Println(bytes.Count(s, sep3)) //9
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
true
false
1
2
9

[Done] exited with code=0 in 1.03 seconds

1.6 替换

func Replace(s, old, new []byte, n int) []bytefunc Map(mapping func(r rune) rune, s []byte) []bytefunc Runes(s []byte) []rune

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	s := []byte("hello,world")
	old := []byte("o")
	news := []byte("ee")
	fmt.Println(string(bytes.Replace(s, old, news, 0)))  //hello,world
	fmt.Println(string(bytes.Replace(s, old, news, 1)))  //hellee,world
	fmt.Println(string(bytes.Replace(s, old, news, 2)))  //hellee,weerld
	fmt.Println(string(bytes.Replace(s, old, news, -1))) //hellee,weerld

	s1 := []byte("你好世界")
	r := bytes.Runes(s1)
	fmt.Println("转换前字符串的长度:", len(s1)) //12
	fmt.Println("转换后字符串的长度:", len(r))  //4
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
hello,world
hellee,world
hellee,weerld
hellee,weerld
转换前字符串的长度: 12
转换后字符串的长度: 4

[Done] exited with code=0 in 0.933 seconds

1.7 常用函数总结

func Contains(b, subslice []byte) boolfunc Count(s, sep []byte) intfunc Repeat(b []byte, count int) []bytecfunc Replace(s, old, new []byte, n int) []bytefunc Runes(s []byte) []runefunc Join(s [][]byte, sep []byte) []byte

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	//Contains
	b := []byte("hello world") //字符串强转为byte切片
	sublice1 := []byte("hello w")
	sublice2 := []byte("Hello w")
	fmt.Println(bytes.Contains(b, sublice1)) //true
	fmt.Println(bytes.Contains(b, sublice2)) //false

	//Count
	s := []byte("hellooooooooo")
	sep1 := []byte("h")
	sep2 := []byte("l")
	sep3 := []byte("o")
	fmt.Println(bytes.Count(s, sep1)) //1
	fmt.Println(bytes.Count(s, sep2)) //2
	fmt.Println(bytes.Count(s, sep3)) //9

	//Repeat
	b = []byte("hi")
	fmt.Println(string(bytes.Repeat(b, 1))) //hi
	fmt.Println(string(bytes.Repeat(b, 3))) //hihihi

	//Replace
	s = []byte("hello,world")
	old := []byte("o")
	news := []byte("ee")
	fmt.Println(string(bytes.Replace(s, old, news, 0)))  //hello,world
	fmt.Println(string(bytes.Replace(s, old, news, 1)))  //hellee,world
	fmt.Println(string(bytes.Replace(s, old, news, 2)))  //hellee,weerld
	fmt.Println(string(bytes.Replace(s, old, news, -1))) //hellee,weerld

	//Runes
	s = []byte("你好世界")
	r := bytes.Runes(s)
	fmt.Println("转换前字符串的长度:", len(s)) //12
	fmt.Println("转换后字符串的长度:", len(r)) //4

	//Join
	s2 := [][]byte{[]byte("你好"), []byte("世界")}
	sep4 := []byte(",")
	fmt.Println(string(bytes.Join(s2, sep4))) //你好,世界
	sep5 := []byte("#")
	fmt.Println(string(bytes.Join(s2, sep5))) //你好#世界

}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
true
false
1
2
9
hi
hihihi
hello,world
hellee,world
hellee,weerld
hellee,weerld
转换前字符串的长度: 12
转换后字符串的长度: 4
你好,世界
你好#世界

[Done] exited with code=0 in 1.146 seconds
二 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)]
  	bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
  	lastRead  readOp   // last read operation, so that Unread* can work correctly.
  
  	// FIXME: it would be advisable to align Buffer to cachelines to avoid false
  	// sharing.
}

2.1 声明Buffer的方法

var b bytes.Bufferb := new(bytes.Buffer)b := bytes.NewBuffer(s []byte)b := bytes.NewBufferString(s string)

2.2 往Buffer中写入数据

b.Write(d []byte)b.WriteString(s string)b.WriteByte(c byte)b.WriteRune(r rune)b.WriteTo(w io.Writer)

2.3 从Buffer中读取数据到指定容器

c := make([]byte, 8)
b.Read(c)b.ReadByte()a, _ := b.ReadByte()b.ReadRune()r, _ := b.ReadRune()b.ReadBytes(delimiter byte)b.ReadString(delimiter byte)b.ReadFrom(i io.Reader)

2.4 实例演示

package main

import (
	"bytes"
	"fmt"
)

func main() {
	rd := bytes.NewBufferString("Hello World!")
	buf := make([]byte, 6)
	// 获取数据切片
	b := rd.Bytes()
	// 读出一部分数据,看看切片有没有变化
	rd.Read(buf)
	fmt.Printf("%s\n", rd.String())
	fmt.Printf("%s\n\n", b)

	// 写入一部分数据,看看切片有没有变化
	rd.Write([]byte("abcdefg"))
	fmt.Printf("%s\n", rd.String())
	fmt.Printf("%s\n\n", b)

	// 再读出一部分数据,看看切片有没有变化
	rd.Read(buf)
	fmt.Printf("%s\n", rd.String())
	fmt.Printf("%s\n", b)
}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
World!
Hello World!

World!abcdefg
Hello World!

abcdefg
Hello World!

[Done] exited with code=0 in 1.028 seconds

2.5 其他相关方法

func (b *Buffer) Len() intfunc (b *Buffer) Cap() intfunc (b *Buffer) Next(n int) []bytefunc (b *Buffer) Bytes() []bytefunc (b *Buffer) String() stringfunc (b *Buffer) Grow(n int)func (b *Buffer) Truncate(n int)func (b *Buffer) Reset()
三 Reader类型
type Reader struct {
  	s        []byte
  	i        int64 // current reading index
  	prevRune int   // index of previous rune; or < 0
}
io.Readerio.ReaderAtio.WriterToio.Seekerio.ByteScannerio.RuneScanner

相关方法:

func NewReader(b []byte) *Readerfunc (r *Reader) Len() intfunc (r *Reader) Size() int64func (r *Reader) Reset(b []byte)

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	data := "123456789"
	//通过[]byte创建Reader
	re := bytes.NewReader([]byte(data))
	//返回未读取部分的长度
	fmt.Println("re len : ", re.Len())
	//返回底层数据总长度
	fmt.Println("re size : ", re.Size())

	fmt.Println("---------------")

	buf := make([]byte, 2)
	for {
		//读取数据
		n, err := re.Read(buf)
		if err != nil {
			break
		}
		fmt.Println(string(buf[:n]))
	}

}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
re len :  9
re size :  9
---------------
12
34
56
78
9

[Done] exited with code=0 in 0.961 seconds

Reader是只读的、但是是可以seek的。

实例演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	data := "123456789"
	//通过[]byte创建Reader
	re := bytes.NewReader([]byte(data))

	buf := make([]byte, 2)

	re.Seek(0, 0)
	//设置偏移量
	for {
		//一个字节一个字节的读
		b, err := re.ReadByte()
		if err != nil {
			break
		}
		fmt.Println(string(b))
	}
	fmt.Println("----------------")

	re.Seek(0, 0)
	off := int64(0)
	for {
		//指定偏移量读取
		n, err := re.ReadAt(buf, off)
		if err != nil {
			break
		}
		off += int64(n)
		fmt.Println(off, string(buf[:n]))
	}

}

运行结果:

[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
1
2
3
4
5
6
7
8
9
----------------
2 12
4 34
6 56
8 78

[Done] exited with code=0 in 0.921 seconds