golang标准包分析—bytes


bytes包对外提供的函数

这里将函数分为两类,一类是汇编(这种只需要明白用法就行),一类是使用代码实现的(这种需要好好学习)

// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
func Index(s, sep []byte) int {```}
这个函数内部的核心函数是bytealg.Index(),此函数属于汇编类型,用处就是返回首个存在于s中的sep实例的索引,如果不存在返回-1

// Compare returns an integer comparing two byte slices lexicographically.
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
// A nil argument is equivalent to an empty slice.
func Compare(a, b []byte) int // in internal/bytealg
此函数从注释上可以看出是按照字典顺序比较两组切片的大小,实际测试发现是对应索引的相互比较,
如果切片长度一致,a[i] != b[i]就返回结果,否则返回0,
如果切片长度不一致,先比较对应索引的值,如果都一样,则看切片长度,长的大返回1

// Contains reports whether subslice is within b.
func Contains(b, subslice []byte) bool {
    return Index(b, subslice) != -1
}
此函数调用的是Index()函数
<!-- 他会返回chars中任意一个unicode代码点第一次出现在s的字节索引 -->
// ContainsAny reports whether any of the UTF-8-encoded code points in chars are within b.
func ContainsAny(b []byte, chars string) bool {
    return IndexAny(b, chars) >= 0
}
当b中存在任何一个chars中的字符,返回true
值得学习的是IndexAny中对acsii码字符的处理

    if len(s) > 8 {
        if as, isASCII := makeASCIISet(chars); isASCII {
            for i, c := range s {
                if as.contains(c) {
                    return i
                }
            }
            return -1
        }
    }
当len(s)>8时(虽然不知道为什么需要这一层判断)会将目标字符串(必须是ascii中的字符)存入ASCIISet中

func makeASCIISet(chars string) (as asciiSet, ok bool) {
    for i := 0; i < len(chars); i++ {
        c := chars[i]
        if c >= utf8.RuneSelf {
            return as, false
        }
        as[c>>5] |= 1 << uint(c&31)
    }
    return as, true
}

这里是将字符右移5位,bits[5:8]作为Set的索引,右移后的索引范围在0-7
值的储存范围是4个字节,32个bit位,通过位移的方式将值通过高低位的方式存在对应的bit位上
例子:
字符      十进制     二进制 位移后对应的索引     存储的位置
1       49      00110001    1   0000 0000 0000 0010 0000 0000 0000 0000
2       50      00110010    1   0000 0000 0000 0100 0000 0000 0000 0000 

如果128ascii字符都存进set中,将会占满前4个字节,每个字节中的bit的高位1都表示各个ascii字符存在其中

// contains reports whether c is inside the set.
func (as *asciiSet) contains(c byte) bool {
    return (as[c>>5] & (1 << uint(c&31))) != 0
}
通过contains函数,判断set中的对应字符是否存在

See also