这个库是关于 []byte 操作的一些内容,它之于 []byte 就像 strings 库之于 string ,不过好像很多函数挺复杂的,因为还有个 rune 类型混入其中。

bytes.go

这里面全是些功能函数,没有涉及到接口结构体之类的,所以就简单过了一下。


有意思的是,子字符串匹配用的算法是 Rabin-Karp 算法,比如 LastIndex 函数

  1. // src/bytes/bytes.go ---- line 103
  2. // LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
  3. func LastIndex(s, sep []byte) int {
  4. n := len(sep)
  5. switch {
  6. case n == 0:
  7. return len(s)
  8. case n == 1:
  9. return LastIndexByte(s, sep[0])
  10. case n == len(s):
  11. if Equal(s, sep) {
  12. return 0
  13. }
  14. return -1
  15. case n > len(s):
  16. return -1
  17. }
  18. // Rabin-Karp search from the end of the string
  19. hashss, pow := hashStrRev(sep)
  20. last := len(s) - n
  21. var h uint32
  22. for i := len(s) - 1; i >= last; i-- {
  23. h = h*primeRK + uint32(s[i])
  24. }
  25. if h == hashss && Equal(s[last:], sep) {
  26. return last
  27. }
  28. for i := last - 1; i >= 0; i-- {
  29. h *= primeRK
  30. h += uint32(s[i])
  31. h -= pow * uint32(s[i+n])
  32. if h == hashss && Equal(s[i:i+n], sep) {
  33. return i
  34. }
  35. }
  36. return -1
  37. }
  38. // src/bytes/bytes.go ---- line 1104
  39. // primeRK is the prime base used in Rabin-Karp algorithm.
  40. const primeRK = 16777619
  41. // hashStr returns the hash and the appropriate multiplicative
  42. // factor for use in Rabin-Karp algorithm.
  43. func hashStr(sep []byte) (uint32, uint32) {
  44. hash := uint32(0)
  45. for i := 0; i < len(sep); i++ {
  46. hash = hash*primeRK + uint32(sep[i])
  47. }
  48. var pow, sq uint32 = 1, primeRK
  49. for i := len(sep); i > 0; i >>= 1 {
  50. if i&1 != 0 {
  51. pow *= sq
  52. }
  53. sq *= sq
  54. }
  55. return hash, pow
  56. }
  57. // hashStrRev returns the hash of the reverse of sep and the
  58. // appropriate multiplicative factor for use in Rabin-Karp algorithm.
  59. func hashStrRev(sep []byte) (uint32, uint32) {
  60. hash := uint32(0)
  61. for i := len(sep) - 1; i >= 0; i-- {
  62. hash = hash*primeRK + uint32(sep[i])
  63. }
  64. var pow, sq uint32 = 1, primeRK
  65. for i := len(sep); i > 0; i >>= 1 {
  66. if i&1 != 0 {
  67. pow *= sq
  68. }
  69. sq *= sq
  70. }
  71. return hash, pow
  72. }

这个算法的核心想法是把字符串表示成整数来进行比较,这样效率会比较高,有时间再来写个逐行的分析。


其中还有个这样的数组

  1. // src/bytes/bytes.go ---- line 307
  2. var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}

最开始看到还没看懂,其实字符就是 uint8 嘛,这样写只是为了好理解,把算作空字符的位置置 1,其他都默认 0, 后面用于判断。判断字符 r 是不是 space

  1. // src/bytes/bytes.go ---- line 323
  2. isSpace := int(asciiSpace[r])

buffer.go

这个就是对 []byte 类型的一种封装,也就是 Buffer 结构体,实现了 io.ReadWriter 接口

  1. // src/bytes/buffer.go ---- line 18
  2. // A Buffer is a variable-sized buffer of bytes with Read and Write methods.
  3. // The zero value for Buffer is an empty buffer ready to use.
  4. type Buffer struct {
  5. buf []byte // contents are the bytes buf[off : len(buf)]
  6. off int // read at &buf[off], write at &buf[len(buf)]
  7. lastRead readOp // last read operation, so that Unread* can work correctly.
  8. }

整体都很普通,没有太出彩的地方。学会一个 maxInt 的写法

  1. // src/bytes/buffer.go ---- line 47
  2. const maxInt = int(^uint(0) >> 1)

reader.go

这个其实跟上面那个差不多啦,只不过只实现了 io.Reader 接口,就是用于把 []byte 当作一个 Reader 来使用的一种封装。

  1. // src/bytes/reader.go ---- line 13
  2. // A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker,
  3. // io.ByteScanner, and io.RuneScanner interfaces by reading from
  4. // a byte slice.
  5. // Unlike a Buffer, a Reader is read-only and supports seeking.
  6. // The zero value for Reader operates like a Reader of an empty slice.
  7. type Reader struct {
  8. s []byte
  9. i int64 // current reading index
  10. prevRune int // index of previous rune; or < 0
  11. }