美文网首页
高效地使用字符串(Golang)

高效地使用字符串(Golang)

作者: 勿以浮沙筑高台 | 来源:发表于2017-08-03 20:23 被阅读200次

    字符串是不可变字节(byte)序列,默认值是"",而不是nil
    使用 “`” 定义的原始字符串(raw strubg),支持跨行。字符串支持 !=、==、<、>、+、+= 操作符。允许以索引号访问字节数组,但不能获取元素地址。

    使用 for 遍历字符串时,分 byterune 两种方式。

    转换
    修改字符串,需将其转换为可变类型([]byte[]rune),待完成后再转换回来。这个过程将重新分配内存,并复制数据。这个转换过程有一定的性能损失。要想获得更好的性能可以使用 “非安全” 的方式进行改善。

    func bytesToString(bs []byte) string {
      return *(*string)(unsafe.Pointer(&bs))
    }
    

    亦可以用同样的方式将 string 转换为 []byte。只不过得到的字节序列是不可修改的,当尝试修改时,会得到如下类似错误:

    unexpected fault address 0x1066146
    fatal error: fault
    [signal SIGBUS: bus error code=0x2 addr=0x1066146 pc=0x104bff0]
    

    动态构建字符串
    + 拼接字符串时,每次都会重新分配内存。在拼接超多字符串时,性能将显得极差。
    改进的思路是分配足够的内存空间,减少内存分配的次数。常用方法是 strings.Join 函数,其实现如下:

    func Join(a []string, sep string) string {
        if len(a) == 0 {
            return ""
        }
        if len(a) == 1 {
            return a[0]
        }
        n := len(sep) * (len(a) - 1)
        for i := 0; i < len(a); i++ {
            n += len(a[i])
        }
        
        b := make([]byte, n)
        bp := copy(b, a[0])
        for _, s := range a[1:] {
            bp += copy(b[bp:], sep)
            bp += copy(b[bp:], s)
        }
        return string(b)
    }   
    

    结合前面的内容,可以对 Join 函数稍作修改,减少一次内存分配和内容复制操作。

    func Join(a []string, sep string) string { 
      ……
      return toString(b)
    }
    

    相关文章

      网友评论

          本文标题:高效地使用字符串(Golang)

          本文链接:https://www.haomeiwen.com/subject/qkxmlxtx.html