使用过哪些 golang 的 String 类库

参考解析

题目来源:小米

答案:

string.builder

Go 语言提供了一个专门操作字符串的库 strings,可以用于字符串查找、替换、比较等。

使用 strings.Builder 可以进行字符串拼接,提供了 writeString 方法拼接字符串,使用方式如下:

  1. var builder strings.Builder
  2. builder.WriteString("asong")
  3. builder.String()

strings.builder 的实现原理很简单,结构如下:

  1. type Builder struct {
  2. addr *Builder // of receiver, to detect copies by value
  3. buf []byte // 1
  4. }

addr 字段主要是做 copycheckbuf 字段是一个 byte 类型的切片,这个就是用来存放字符串内容的,提供的 writeString() 方法就是向切片 buf 中追加数据:

  1. func (b *Builder) WriteString(s string) (int, error) {
  2. b.copyCheck()
  3. b.buf = append(b.buf, s...)
  4. return len(s), nil
  5. }

提供的 String 方法就是将 []byte 转换为 string 类型,这里为了避免内存拷贝的问题,使用了强制转换来避免内存拷贝:

  1. func (b *Builder) String() string {
  2. return *(*string)(unsafe.Pointer(&b.buf))
  3. }

bytes.Buffer

因为 string 类型底层就是一个 byte 数组,所以我们就可以 Go 语言的 bytes.Buffer 进行字符串拼接。bytes.Buffer 是一个一个缓冲 byte 类型的缓冲器,这个缓冲器里存放着都是 byte。使用方式如下:

  1. buf := new(bytes.Buffer)
  2. buf.WriteString("asong")
  3. buf.String()

bytes.buffer 底层也是一个 []byte 切片,结构体如下:

  1. type Buffer struct {
  2. buf []byte // contents are the bytes buf[off : len(buf)]
  3. off int // read at &buf[off], write at &buf[len(buf)]
  4. lastRead readOp // last read operation, so that Unread* can work correctly.
  5. }

因为 bytes.Buffer 可以持续向 Buffer 尾部写入数据,从 Buffer 头部读取数据,所以 off 字段用来记录读取位置,再利用切片的 cap 特性来知道写入位置,这个不是本次的重点,重点看一下 WriteString 方法是如何拼接字符串的:

  1. func (b *Buffer) WriteString(s string) (n int, err error) {
  2. b.lastRead = opInvalid
  3. m, ok := b.tryGrowByReslice(len(s))
  4. if !ok {
  5. m = b.grow(len(s))
  6. }
  7. return copy(b.buf[m:], s), nil
  8. }

切片在创建时并不会申请内存块,只有在往里写数据时才会申请,首次申请的大小即为写入数据的大小。如果写入的数据小于64字节,则按64字节申请。采用 动态扩展slice 的机制,字符串追加采用 copy 的方式将追加的部分拷贝到尾部,copy是内置的拷贝函数,可以减少内存分配。

但是在将 []byte 转换为 string 类型依旧使用了标准类型,所以会发生内存分配:

  1. func (b *Buffer) String() string {
  2. if b == nil {
  3. // Special case, useful in debugging.
  4. return "<nil>"
  5. }
  6. return string(b.buf[b.off:])
  7. }

参考资料
Go 字符串拼接的6种最快方式–strings.builder
https://www.cnblogs.com/cheyunhua/p/15769717.html

Go标准库(一):strings包(字符串操作)使用
https://zhuanlan.zhihu.com/p/375953005

Go语言中字符串转换包strconv
https://zhuanlan.zhihu.com/p/160814669