Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go 语言标准库 —— bytes 包(字节切片操作)


🔹 概述

bytes 包提供了用于操作字节切片([]byte)的函数,类似于 strings 包对字符串的操作。

主要功能:

  • 字节切片比较、查找、分割
  • 字节切片与字符串转换
  • Buffer 缓冲区操作
  • Reader 读取器

🔹 Buffer 类型

字节缓冲区

bytes.Buffer struct

  • 说明:

    • 实现了 io.Reader、io.Writer、io.ByteReader、io.ByteWriter 等接口
    • 内部维护一个可增长的字节缓冲区
    • 适合用于高效地构建或处理字节数据
  • 字段:

    • 内部自动管理,无需手动操作
  • 常用方法详解

    • Write 方法

      • 说明:写入字节切片
      • 方法:Write(p []byte) (n int, err error)
      • 注意:缓冲区会自动扩展
      • 示例:
        var buf bytes.Buffer
        buf.Write([]byte("hello"))
        
    • WriteString 方法

      • 说明:写入字符串
      • 方法:WriteString(s string) (n int, err error)
      • 注意:避免字符串到 []byte 的转换
      • 示例:
        var buf bytes.Buffer
        buf.WriteString("hello")
        
    • WriteByte 方法

      • 说明:写入单个字节
      • 方法:WriteByte(c byte) error
      • 注意:最高效的写入方式
      • 示例:
        var buf bytes.Buffer
        buf.WriteByte('A')
        
    • WriteRune 方法

      • 说明:写入单个 rune(Unicode 字符)
      • 方法:WriteRune(r rune) (n int, err error)
      • 注意:自动进行 UTF-8 编码
      • 示例:
        var buf bytes.Buffer
        buf.WriteRune('中')
        
    • Read 方法

      • 说明:从缓冲区读取数据
      • 方法:Read(p []byte) (n int, err error)
      • 注意:读取后数据会从缓冲区移除
      • 示例:
        buf := bytes.NewBuffer([]byte("hello"))
        data := make([]byte, 5)
        buf.Read(data)
        
    • ReadByte 方法

      • 说明:读取并返回下一个字节
      • 方法:ReadByte() (byte, error)
      • 示例:
        b, _ := buf.ReadByte()
        
    • Bytes 方法

      • 说明:返回缓冲区内容的字节切片
      • 方法:Bytes() []byte
      • 注意:返回的切片在下一次写操作后会失效
      • 示例:
        data := buf.Bytes()
        
    • String 方法

      • 说明:返回缓冲区内容的字符串
      • 方法:String() string
      • 注意:不会复制底层数据(高效)
      • 示例:
        result := buf.String()
        
    • Len 方法

      • 说明:返回缓冲区中可读的字节数
      • 方法:Len() int
      • 示例:
        length := buf.Len()
        
    • Cap 方法

      • 说明:返回缓冲区的容量
      • 方法:Cap() int
      • 示例:
        capacity := buf.Cap()
        
    • Reset 方法

      • 说明:清空缓冲区,复用缓冲区
      • 方法:Reset()
      • 注意:不会释放内存,可重复使用
      • 示例:
        buf.Reset() // 清空
        
    • Truncate 方法

      • 说明:截断缓冲区,保留前 n 个字节
      • 方法:Truncate(n int)
      • 注意:n 必须 >= 0
      • 示例:
        buf.Truncate(5) // 保留前 5 字节
        
    • Grow 方法

      • 说明:预分配容量
      • 方法:Grow(n int)
      • 注意:知道最终大小时使用,减少内存分配
      • 示例:
        buf.Grow(1024) // 预分配 1024 字节
        
    • UnreadByte 方法

      • 说明:回退一个字节
      • 方法:UnreadByte() error
      • 注意:只能回退最近读取的一个字节
      • 示例:
        buf.UnreadByte()
        
  • 示例(完整)

    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	var buf bytes.Buffer
    
    	// 预分配容量
    	buf.Grow(100)
    
    	// 写入数据
    	buf.WriteString("hello ")
    	buf.WriteByte('G')
    	buf.WriteString("o")
    	buf.WriteRune('!')
    
    	// 查看内容
    	fmt.Println("内容:", buf.String())
    	fmt.Println("长度:", buf.Len())
    	fmt.Println("容量:", buf.Cap())
    
    	// 读取
    	data := buf.Bytes()
    	fmt.Println("字节:", data)
    
    	// 清空并复用
    	buf.Reset()
    	buf.WriteString("world")
    	fmt.Println("重置后:", buf.String())
    }
    
  • 使用场景示例

    • 高效构建字符串

      • 示例:
        var buf bytes.Buffer
        for i := 0; i < 1000; i++ {
        	buf.WriteString(fmt.Sprintf("%d,", i))
        }
        result := buf.String()
        
    • 作为 io.Writer 使用

      • 示例:
        var buf bytes.Buffer
        io.Copy(&buf, file)
        data := buf.Bytes()
        
    • 作为 io.Reader 使用

      • 示例:
        buf := bytes.NewBuffer([]byte("data"))
        io.Copy(os.Stdout, buf)
        
    • 临时数据存储

      • 示例:
        var buf bytes.Buffer
        buf.Write(header)
        buf.Write(body)
        send(buf.Bytes())
        

🔹 Reader 类型

字节读取器

bytes.Reader struct

  • 说明:

    • 实现了 io.Reader、io.Seeker、io.ReaderAt 等接口
    • 从字节切片读取数据,支持随机访问
    • 类似 strings.Reader,但操作的是 []byte
  • 常用方法详解

    • Read 方法

      • 说明:从读取器读取数据
      • 方法:Read(p []byte) (n int, err error)
      • 注意:读取后内部偏移量会移动
      • 示例:
        r := bytes.NewReader([]byte("hello"))
        data := make([]byte, 5)
        r.Read(data)
        
    • ReadAt 方法

      • 说明:从指定位置读取
      • 方法:ReadAt(p []byte, off int64) (n int, err error)
      • 注意:不影响内部偏移量
      • 示例:
        r := bytes.NewReader([]byte("hello"))
        data := make([]byte, 3)
        r.ReadAt(data, 2) // 从位置 2 读取
        
    • Seek 方法

      • 说明:移动读取位置
      • 方法:Seek(offset int64, whence int) (int64, error)
      • 注意:whence=0 从头,1 从当前位置,2 从末尾
      • 示例:
        r := bytes.NewReader([]byte("hello"))
        r.Seek(2, 0) // 移动到位置 2
        
    • Len 方法

      • 说明:返回未读取的字节数
      • 方法:Len() int
      • 示例:
        remaining := r.Len()
        
    • Size 方法

      • 说明:返回总字节数
      • 方法:Size() int64
      • 示例:
        total := r.Size()
        
    • Reset 方法

      • 说明:重置为读取新的字节切片
      • 方法:Reset(b []byte)
      • 注意:复用 Reader
      • 示例:
        r.Reset([]byte("new data"))
        
  • 示例(完整)

    package main
    
    import (
    	"fmt"
    	"bytes"
    	"io"
    )
    
    func main() {
    	data := []byte("hello world")
    	r := bytes.NewReader(data)
    
    	// 读取全部
    	all, _ := io.ReadAll(r)
    	fmt.Println("全部:", string(all))
    
    	// 重置并随机访问
    	r.Reset(data)
    	r.Seek(6, 0) // 移动到 "world"
    
    	buf := make([]byte, 5)
    	r.Read(buf)
    	fmt.Println("读取:", string(buf))
    
    	// ReadAt(不影响偏移量)
    	buf2 := make([]byte, 5)
    	r.ReadAt(buf2, 0) // 从头读取
    	fmt.Println("ReadAt:", string(buf2))
    }
    
  • 使用场景示例

    • 模拟 io.Reader

      • 示例:
        data := []byte("test data")
        r := bytes.NewReader(data)
        io.Copy(os.Stdout, r)
        
    • 测试代码

      • 示例:
        func TestRead(t *testing.T) {
        	r := bytes.NewReader([]byte("test"))
        	// 测试读取逻辑
        }
        
    • 内存中的随机访问

      • 示例:
        r := bytes.NewReader(fileData)
        r.Seek(100, 0) // 跳到位置 100
        r.Read(buf)    // 读取数据
        

🔹 比较函数

字节切片比较

bytes.Equal(a, b []byte) bool

  • 说明:
    • 比较两个字节切片是否相等
    • 长度和内容都必须相同
  • 返回值:
    • true 👉 相等
    • false 👉 不相等
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.Equal([]byte("hello"), []byte("hello"))) // true
    	fmt.Println(bytes.Equal([]byte("hello"), []byte("world"))) // false
    	fmt.Println(bytes.Equal([]byte{}, []byte(nil))) // true(空和 nil 相等)
    }
    

带前缀比较

bytes.EqualFold(s, t []byte) bool

  • 说明:
    • 忽略大小写比较两个字节切片
    • 支持 ASCII 字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.EqualFold([]byte("Hello"), []byte("hello"))) // true
    	fmt.Println(bytes.EqualFold([]byte("Go"), []byte("GO"))) // true
    	fmt.Println(bytes.EqualFold([]byte("test"), []byte("best"))) // false
    }
    

比较两个字节切片

bytes.Compare(a, b []byte) int

  • 说明:
    • 按字典序比较两个字节切片
    • 基于字节值的比较
  • 返回值:
    • 0 👉 a == b
    • -1 👉 a < b
    • 1 👉 a > b
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.Compare([]byte("a"), []byte("b"))) // -1
    	fmt.Println(bytes.Compare([]byte("a"), []byte("a"))) // 0
    	fmt.Println(bytes.Compare([]byte("b"), []byte("a"))) // 1
    }
    

🔹 查找函数

包含子切片

bytes.Contains(b, subslice []byte) bool

  • 说明:
    • 检查字节切片 b 是否包含子切片 subslice
  • 返回值:
    • true 👉 包含
    • false 👉 不包含
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.Contains([]byte("hello world"), []byte("world"))) // true
    	fmt.Println(bytes.Contains([]byte("hello"), []byte("x"))) // false
    }
    

包含任意字节

bytes.ContainsAny(b []byte, chars string) bool

  • 说明:
    • 检查字节切片 b 是否包含 chars 中的任意字节
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.ContainsAny([]byte("hello"), "aei")) // true
    	fmt.Println(bytes.ContainsAny([]byte("hello"), "xyz")) // false
    }
    

包含指定字节

bytes.ContainsRune(b []byte, r rune) bool

  • 说明:
    • 检查字节切片 b 是否包含指定 rune
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.ContainsRune([]byte("hello"), 'e')) // true
    	fmt.Println(bytes.ContainsRune([]byte("hello"), 'x')) // false
    }
    

统计出现次数

bytes.Count(s, sep []byte) int

  • 说明:
    • 统计子切片 sep 在 s 中出现的次数
    • 非重叠计数
  • 特殊情况:
    • sep 为空时返回 len(s) + 1
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.Count([]byte("banana"), []byte("na"))) // 2
    	fmt.Println(bytes.Count([]byte("aaaa"), []byte("aa"))) // 2
    	fmt.Println(bytes.Count([]byte("hello"), []byte("x"))) // 0
    }
    

查找子切片位置

bytes.Index(b, subslice []byte) int

  • 说明:
    • 返回子切片第一次出现的位置
    • 未找到返回 -1
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.Index([]byte("hello world"), []byte("world"))) // 6
    	fmt.Println(bytes.Index([]byte("hello"), []byte("x"))) // -1
    }
    

查找任意字节位置

bytes.IndexAny(b []byte, chars string) int

  • 说明:
    • 返回 chars 中任意字节第一次出现的位置
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.IndexAny([]byte("hello"), "aei")) // 1(e 的位置)
    	fmt.Println(bytes.IndexAny([]byte("hello"), "xyz")) // -1
    }
    

查找指定字节位置

bytes.IndexByte(b []byte, c byte) int

  • 说明:
    • 返回指定字节第一次出现的位置
    • 比 Index 更高效(针对单字节)
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.IndexByte([]byte("hello"), 'e')) // 1
    	fmt.Println(bytes.IndexByte([]byte("hello"), 'x')) // -1
    }
    

最后一个子切片位置

bytes.LastIndex(b, subslice []byte) int

  • 说明:
    • 返回子切片最后一次出现的位置
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.LastIndex([]byte("banana"), []byte("na"))) // 4
    	fmt.Println(bytes.LastIndex([]byte("hello"), []byte("l"))) // 3
    }
    

🔹 分割函数

按子切片分割

bytes.Split(s, sep []byte) [][]byte

  • 说明:
    • 使用 sep 分割字节切片 s
    • 返回分割后的切片数组
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	parts := bytes.Split([]byte("a,b,c"), []byte(","))
    	for i, p := range parts {
    		fmt.Printf("%d: %s\n", i, string(p))
    	}
    	// 0: a
    	// 1: b
    	// 2: c
    }
    

分割 N 次

bytes.SplitN(s, sep []byte, n int) [][]byte

  • 说明:
    • 最多分割 n-1 次,返回 n 个部分
    • n < 0 表示不限制次数
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	// 分割 2 次,返回 3 部分
    	parts := bytes.SplitN([]byte("a,b,c,d"), []byte(","), 3)
    	fmt.Printf("分割 2 次:%v\n", parts)
    	// [a b c,d]
    
    	// 不限制
    	parts2 := bytes.SplitN([]byte("a,b,c"), []byte(","), -1)
    	fmt.Printf("不限制:%v\n", parts2)
    	// [a b c]
    }
    

分割成多行

bytes.SplitAfter(s, sep []byte) [][]byte

  • 说明:
    • 类似 Split,但保留分隔符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	parts := bytes.SplitAfter([]byte("a;b;c;"), []byte(";"))
    	for i, p := range parts {
    		fmt.Printf("%d: %s\n", i, string(p))
    	}
    	// 0: a;
    	// 1: b;
    	// 2: c;
    }
    

分割 N 次并保留分隔符

bytes.SplitAfterN(s, sep []byte, n int) [][]byte

  • 说明:
    • SplitAfter 的 N 次版本
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	parts := bytes.SplitAfterN([]byte("a,b,c,d"), []byte(","), 2)
    	fmt.Printf("%v\n", parts)
    	// [a, b,c,d]
    }
    

🔹 修剪函数

修剪空白字符

bytes.TrimSpace(s []byte) []byte

  • 说明:
    • 移除首尾的空白字符(空格、制表符、换行等)
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("  \t\nhello world  \t\n")
    	trimmed := bytes.TrimSpace(s)
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello world
    }
    

修剪指定字节

bytes.Trim(s []byte, cutset string) []byte

  • 说明:
    • 移除首尾在 cutset 中的任意字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("###hello###")
    	trimmed := bytes.Trim(s, "#")
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello
    }
    

修剪前缀

bytes.TrimPrefix(s, prefix []byte) []byte

  • 说明:
    • 如果 s 以 prefix 开头,则移除 prefix
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("http://example.com")
    	trimmed := bytes.TrimPrefix(s, []byte("http://"))
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// example.com
    }
    

修剪后缀

bytes.TrimSuffix(s, suffix []byte) []byte

  • 说明:
    • 如果 s 以后缀 suffix 结尾,则移除 suffix
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("file.txt")
    	trimmed := bytes.TrimSuffix(s, []byte(".txt"))
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// file
    }
    

修剪左侧字符

bytes.TrimLeft(s []byte, cutset string) []byte

  • 说明:
    • 只移除左侧(开头)在 cutset 中的字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("###hello###")
    	trimmed := bytes.TrimLeft(s, "#")
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello###
    }
    

修剪右侧字符

bytes.TrimRight(s []byte, cutset string) []byte

  • 说明:
    • 只移除右侧(结尾)在 cutset 中的字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("###hello###")
    	trimmed := bytes.TrimRight(s, "#")
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// ###hello
    }
    

修剪左侧函数

bytes.TrimLeftFunc(s []byte, f func(rune) bool) []byte

  • 说明:
    • 使用条件函数判断是否移除左侧字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    	"unicode"
    )
    
    func main() {
    	s := []byte("  \thello")
    	trimmed := bytes.TrimLeftFunc(s, unicode.IsSpace)
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello
    }
    

修剪右侧函数

bytes.TrimRightFunc(s []byte, f func(rune) bool) []byte

  • 说明:
    • 使用条件函数判断是否移除右侧字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    	"unicode"
    )
    
    func main() {
    	s := []byte("hello  \t")
    	trimmed := bytes.TrimRightFunc(s, unicode.IsSpace)
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello
    }
    

修剪两侧函数

bytes.TrimFunc(s []byte, f func(rune) bool) []byte

  • 说明:
    • 使用条件函数判断是否移除两侧字符
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    	"unicode"
    )
    
    func main() {
    	s := []byte("  hello  ")
    	trimmed := bytes.TrimFunc(s, unicode.IsSpace)
    	fmt.Printf("修剪后:%s\n", string(trimmed))
    	// hello
    }
    

🔹 替换函数

替换子切片

bytes.Replace(s, old, new []byte, n int) []byte

  • 说明:
    • 替换 s 中的 old 为 new
    • n < 0 表示替换所有,n >= 0 表示最多替换 n 次
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	// 替换所有
    	s := bytes.Replace([]byte("hello world"), []byte("world"), []byte("Go"), -1)
    	fmt.Printf("替换所有:%s\n", string(s))
    	// hello Go
    
    	// 替换 1 次
    	s2 := bytes.Replace([]byte("aa bb aa"), []byte("aa"), []byte("cc"), 1)
    	fmt.Printf("替换 1 次:%s\n", string(s2))
    	// cc bb aa
    }
    

替换所有子切片

bytes.ReplaceAll(s, old, new []byte) []byte

  • 说明:
    • 替换所有出现的 old 为 new
    • Go 1.12+ 新增
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := bytes.ReplaceAll([]byte("aa bb aa"), []byte("aa"), []byte("cc"))
    	fmt.Printf("替换所有:%s\n", string(s))
    	// cc bb cc
    }
    

重复字节切片

bytes.Repeat(b []byte, count int) []byte

  • 说明:
    • 返回 b 重复 count 次后的新切片
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := bytes.Repeat([]byte("ab"), 3)
    	fmt.Printf("重复 3 次:%s\n", string(s))
    	// ababab
    }
    

🔹 大小写转换

转小写

bytes.ToLower(s []byte) []byte

  • 说明:
    • 将所有 ASCII 大写字母转换为小写
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := bytes.ToLower([]byte("HELLO World"))
    	fmt.Printf("小写:%s\n", string(s))
    	// hello world
    }
    

转大写

bytes.ToUpper(s []byte) []byte

  • 说明:
    • 将所有 ASCII 小写字母转换为大写
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := bytes.ToUpper([]byte("hello World"))
    	fmt.Printf("大写:%s\n", string(s))
    	// HELLO WORLD
    }
    

首字母大写

bytes.ToTitle(s []byte) []byte

  • 说明:
    • 将所有字母转换为标题格式(大写)
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := bytes.ToTitle([]byte("hello"))
    	fmt.Printf("标题格式:%s\n", string(s))
    	// HELLO
    }
    

判断是否小写

bytes.IsLower(s []byte) bool

  • 说明:
    • 检查是否所有字母都是小写
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.IsLower([]byte("hello"))) // true
    	fmt.Println(bytes.IsLower([]byte("Hello"))) // false
    }
    

判断是否大写

bytes.IsUpper(s []byte) bool

  • 说明:
    • 检查是否所有字母都是大写
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.IsUpper([]byte("HELLO"))) // true
    	fmt.Println(bytes.IsUpper([]byte("Hello"))) // false
    }
    

判断是否标题格式

bytes.IsTitle(s []byte) bool

  • 说明:
    • 检查是否是标题格式(每个单词首字母大写)
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	fmt.Println(bytes.IsTitle([]byte("Hello"))) // true
    	fmt.Println(bytes.IsTitle([]byte("hello"))) // false
    }
    

🔹 其他函数

转义

bytes.Clone(s []byte) []byte

  • 说明:
    • 返回字节切片的独立副本
    • Go 1.20+ 新增
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	s := []byte("hello")
    	clone := bytes.Clone(s)
    	
    	// 修改原切片不影响副本
    	s[0] = 'H'
    	fmt.Printf("原切片:%s\n", string(s)) // Hello
    	fmt.Printf("副本:%s\n", string(clone)) // hello
    }
    

标题化

bytes.ToValidUTF8(s, replacement []byte) []byte

  • 说明:
    • 将 s 转换为有效的 UTF-8
    • 无效的 UTF-8 序列会被 replacement 替换
    • Go 1.20+ 新增
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	// 包含无效 UTF-8
    	s := []byte("hello\x80\x81world")
    	valid := bytes.ToValidUTF8(s, []byte("?"))
    	fmt.Printf("有效 UTF-8: %s\n", string(valid))
    	// hello?world
    }
    

🔹 辅助函数

创建缓冲区

bytes.NewBuffer(b []byte) *bytes.Buffer

  • 说明:
    • 使用 b 初始化一个新的 Buffer
    • b 的所有权转移给 Buffer
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	buf := bytes.NewBuffer([]byte("hello"))
    	buf.WriteString(" world")
    	fmt.Println(buf.String())
    	// hello world
    }
    

创建字符串缓冲区

bytes.NewBufferString(s string) *bytes.Buffer

  • 说明:
    • 使用字符串 s 初始化一个新的 Buffer
    • 避免字符串到 []byte 的转换
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    )
    
    func main() {
    	buf := bytes.NewBufferString("hello")
    	buf.WriteString(" world")
    	fmt.Println(buf.String())
    	// hello world
    }
    

读取所有

bytes.ReadAll(r io.Reader) ([]byte, error)

  • 说明:
    • 从 r 读取所有数据到字节切片
    • 类似 io.ReadAll
  • 示例(完整)
    package main
    
    import (
    	"fmt"
    	"bytes"
    	"strings"
    )
    
    func main() {
    	r := strings.NewReader("hello world")
    	data, _ := bytes.ReadAll(r)
    	fmt.Printf("读取:%s\n", string(data))
    	// hello world
    }
    

🔥 总结

核心类型

  • bytes.Buffer 👉 可增长的字节缓冲区(实现了 io.Reader/Writer)
  • bytes.Reader 👉 从字节切片读取(支持随机访问)

常用函数

比较:

  • bytes.Equal() 👉 比较是否相等
  • bytes.EqualFold() 👉 忽略大小写比较
  • bytes.Compare() 👉 字典序比较

查找:

  • bytes.Contains() 👉 包含子切片
  • bytes.Index() 👉 查找位置
  • bytes.LastIndex() 👉 最后出现位置
  • bytes.Count() 👉 统计次数

分割:

  • bytes.Split() 👉 分割切片
  • bytes.SplitN() 👉 分割 N 次
  • bytes.SplitAfter() 👉 保留分隔符

修剪:

  • bytes.TrimSpace() 👉 修剪空白
  • bytes.TrimPrefix() 👉 修剪前缀
  • bytes.TrimSuffix() 👉 修剪后缀

替换:

  • bytes.Replace() 👉 替换子切片
  • bytes.ReplaceAll() 👉 替换所有
  • bytes.Repeat() 👉 重复切片

大小写:

  • bytes.ToLower() 👉 转小写
  • bytes.ToUpper() 👉 转大写
  • bytes.ToTitle() 👉 标题格式

使用场景

  • Buffer 👉 高效构建字节数据、作为 io.Reader/Writer
  • Reader 👉 从内存读取数据、测试代码
  • 查找函数 👉 日志分析、协议解析
  • 分割函数 👉 解析 CSV、配置文件
  • 修剪函数 👉 清理输入、格式化输出
  • 替换函数 👉 模板处理、文本转换

与 strings 包的区别

  • bytes 👉 操作 []byte,适合二进制数据、网络传输
  • strings 👉 操作 string,适合文本处理
  • 性能 👉 bytes 避免了 string 和 []byte 之间的转换
  • 接口 👉 bytes.Buffer 实现了更多 io 接口

最佳实践

  • 使用 Buffer.Grow() 预分配容量
  • 使用 bytes.Reader 代替 strings.Reader 处理二进制数据
  • 使用 bytes.Equal() 而不是比较两个切片的内容
  • 使用 bytes.TrimSpace() 清理用户输入
  • 使用 bytes.ReplaceAll() 进行全局替换