高效地使用字符串(Golang)

勿以浮沙筑高台 · · 1031 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

字符串是不可变字节(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)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1031 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传