golang标准库 bytes包


似strings包 string 功能 不过bytes包对应的是[]byte
和strings一样不修改传入变量 返回其副本修改后的内容
几种操作 转换 比较 去除 分割 查找 替换
一 转换 将s的副本中所有字符修改成大写 小写  后返回
func ToUpper(s []byte) []byte  //  全部转大写
func ToLower(s []byte) []byte  // 全部转小写
func ToTitle(s []byte) []byte  // 全部转大写
使用指定的映射表将对s的副本中的所有字符进行修改 然后返回
func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte
func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte
func ToTitleSpecial(_case unicode.SpecialCase, s []byte)
将s的副本中的所有单词的首字符修改为Title格式返回
func Title(s []byte) []byte
二 比较两个[]byte nil参数相当于[]byte{}
a < b  返回-1
a == b 返回0
a > b   返回1
func Compare(a, b []byte) int
判断a b是否相等 nil参数相当[]byte{}
func Equal(a, b []byte) bool
判断s t是否相似 忽略大写 小写 标题三种格式的区别
func EqualFold(s, t []byte) bool
三 去除s的副本左右包含cutset中的字符 返回s的副本
func Trim(s []byte, cutset string) []byte
func TrimLeft(s []byte, cutset string) []byte
func TrimRight(s []byte, cutset string) []byte
去掉s副本的左右边中f函数中返回true的字符
func TrimFunc(s []byte, f func(r rune) bool) []byte
func TrimLeftFunc(s []byte, f func(r rune) boo) []byte
func TrimRightFunc(s []byte, f func(r rune) bool) []byte
去除s副本两边的空白 unicode.IsSpace)
func TrimSpace(s []byte) []byte
去掉s副本的前缀prefix 后缀suffix
func TrimPrefix(s, prefix []byte) []byte
func TrimSuffix(s, suffix []byte) []byte
四 分割Split函数以sep为分隔符 将s的副本切割分成多个子串 结果不包含分隔符
如果sep为空 则将s的副本分割成Unicode字符列表
SplitN可以指定分割次数 超出n的部分将不进行分割 n小于0 表示分割所有
func Split(s, sep []byte) [][]byte
func SplitN(s, sep []byte, n int) [][]byte

功能同Spelit 只不过结果包含分隔符 在各个子串尾部
func SplitAfter(s, sep []byte) [][]byte
func SplitAfterN(s, sep []byte, n int) [][]byte

以连续空白为分隔符将s的副本分隔成多个子串 结果不包含分隔符
func Fields(s []byte) [][]byte

以符合f的字符为分隔符将s的副本分割成多个子串 结果不包含分割符
func FieldsFunc(s []byte, f func(rune) bool) [][]byte

以sep为连接符 将子串列表s的副本连接成一个字节串
func Join(s [][]byte, sep []byte) []byte

将子串b重复count次后返回
func Repeat(b []byte, count int) []byte
五 查找判断s是否有前缀prefix 后缀suffix
func HasPrefix(s, prefix []byte) bool
func HasSuffix(s, suffix []byte) bool

判断b中是否包含子串subslice 字符r
func Contains(b, subslice []byte) bool
func ContainsRune(b []byte, r rune) bool
判断b中是否包含chars中的任何一个字符
func ContainsAny(b []byte, chars string) bool

查找子串sep 字节c 字符r 在s中第一次出现的位置 找不到则返回-1
func Index(s, sep []byte) int
func IndexByte(s []byte, c byte) int
func IndexRune(s []byte, r rune) int

查找chars中的任何一个字符在s中第一次出现的位置 找不到则返回-1
func IndexAny(s []byte, chars strings) int

查找符合f的字符在s中第一次出现的位置 找不到则返回-1
func IndexFunc(s []byte, f func(r rune) bool) int

功能同上 只不过查找最后一次出现的位置
func LastIndex(s, sep []byte) int
func LastIndexByte(s []byte, c byte) int
func LastIndexAny(s []byte, chars string) int
func LastIndexFunc(s []byte, f func(r rune) bool) int

获取sep在s中出现的次数
func Count(s, sep []byte) int
六 替换 将s副本中的前n个old替换为new n<0则替换全部
func Replace(s, old, new []byte, n int) []byte

将s副本中字符替换为mapping(r)的返回值 如果mapping返回负值 则丢弃该字符
func Map(mapping func(r rune) rune, s []byte) []byte

将s副本转换为[]rune类型返回
func Runes(s []byte) []rune
type Reader
将切片b封装成bytes.Reader对象
func NewReader(b []byte) *Reader
bytes.Reader实现了如下接口
1 io.ReadeSeeker
2 io.ReaderAt
3 io.WriterTo
4 io.ByteScanner
5 io.RuneScanner
// 返回未读取部分的数据长度
func (r *Reader) Len() int
// 返回底层数据的总长度 方便ReadAt使用 返回值不变
func (r *Reader) Size() int64
type Buffer struct {...}
将buf包装成bytes.Buffer对象
func NewBuffer(buf []byte) *Buffer
转化成bytes.Buffer对象
func NewBufferString(s string) *Buffer
Buffer是一个缓存 没有底层数据 缓存的容量 根据需要自动调整 大多数情况下 new(Buffer) 就足以初始化一个Buffer了
bytes.Buffer实现了如下接口
1 io.ReadWrite
2 io.ReaderFrom
3 io.WriterTo
4 io.ByteWriter
5 io.ByteScanner
6 io.RuneScanner
未读取部分的数据长度
func (b *Buffer) Len() int
缓存的容量
func (b *Buffer) Cap() int
读取前n字节的数据并以切片形式返回 如果数据长度小于n 则全部读取 切片只在下一次读写操作前合法
func (b *Buffer) Next(n int) []byte
读取第一个delim及其之前的内容 返回遇到的错误 一般是io.EOF
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error)
func (b *Buffer) ReadString(delim byte) (line string, err error)
写入r的UTF-8编码 返回写入的字节数和error
保留err是为了匹配bufio.Write的WriteRune
func (b *Buffer) WriteRune(r rune) (n int, err error)
写入s 返回写入的字节数和error
func (b *Buffer) WriteString(s string) (n int, err error)
引用未读取部分的数据部分的数据切片 不移动读取位置
func (b *Buffer) Bytes() []byte
返回未读取部分的数据字符串 不移动读取位置
func (b *Buffer) String() string
自动增加缓存容量 以保证有n字节的剩余空间
如果n小于0或无法增加则会panic
func (b *Buffer) Grow(n int)
将数据长度截短到n字节 如果n小于0或大于Cap则panic
func (b *Buffer) Teuncate(n int)
重设缓冲区 清空所有数据 包括初始内容
func (b *Buffer) Reset
Golang中Buffer高效拼接字符串 及自定义线程安全Buffer
Go 使用 + 合并字符串 方式效率低 每合并一次 都是创建一个新的字符串 就必须遍历复制一次字符串
Go Buffer(线程不安全)
package main
import (
    "bytes"
    "fmt"
)
func main() {
    var buffer bytes.Buffer
    for i := 0; i < 1000; i++ {
        buffer.WriteString("a")
    }
    fmt.Println(buffer.String())
}
用bytes.Buffer 组装字符串 不需要复制 只需要将添加的字符串放在缓存末尾
buffer为什么线程不安全
The Go documentation follows a simple rule:
If it is not explicitly stated that concurrent access to something is safe, it is not.
Go文档遵循一个简单的规则:
如果没有明确声明 并发访问 某事物是安全的 则不是
bytes.Buffer部分源码
// 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.
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.
}
// Write appends the contents of p to the buffer, growing the buffer as
// needed. The return value n is the length of p; err is always nil. If the
// buffer becomes too large, Write will panic with ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {
    b.lastRead = opInvalid
    m := b.grow(len(p))
    return copy(b.buf[m:], p), nil
}
// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is io.EOF (unless len(p) is zero);// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err error) {
    b.lastRead = opInvalid
    if b.off >= len(b.buf) {// Buffer is empty, reset to recover space.
        b.Truncate(0)
        if len(p) == 0 {
            return
        }
        return 0, io.EOF
    }
    n = copy(p, b.buf[b.off:])
    b.off += n
    if n > 0 {
        b.lastRead = opRead
    }
    return
}
对于Buffer的定义 没有关于锁的字段 在write和read函数中也未发现锁的踪影
所以符合上面提到的文档中的rule 即Buffer并发是不安全的
自定义实现并发安全的Buffer
type Buffer struct {
    b bytes.Buffer
    rw sync.RWMutex
}
func (b *Buffer) Read(p []byte) (n int, err error) {
    b.rw.RLock()
    defer b.rw.RUnlock()
    return b.b.Read(p)
}
func (b *Buffer) Write(p []byte) (n int, err error) {
    b.rw.Lock()
    defer b.rw.Unlock()
    return b.b.Write(p)
}
两种锁的区别
sync.Mutex(互斥锁)
当一个goroutine访问的时候 其他goroutine都不能访问 保证了资源的同步 避免了竞争 也降低了性能
sync.RWMutex(读写锁)
非写状态时 多个Goroutine可以同时读 一个Goroutine写的时候 其它Goroutine不能读也不能写 性能好