欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go语言模型:string的底层数据结构与高效操作详解

程序员文章站 2022-06-25 08:03:11
golang的string类型底层数据结构简单,本质也是一个结构体实例,且是const不可变。string的底层数据结构通过下面一个例子来看:string的拼接与修改+操作string类型是一个不可变...

golang的string类型底层数据结构简单,本质也是一个结构体实例,且是const不可变。

string的底层数据结构

通过下面一个例子来看:

string的拼接与修改

+操作

string类型是一个不可变类型,那么任何对string的修改都会新生成一个string的实例,如果是考虑效率的场景就要好好考虑一下如何修改了。先说一下最长用的+操作,同样上面的例子,看一下+操作拼接字符串的反汇编:

因为当前go[2018.11 version: go1.11]的不是遵循默认的x86 calling convention用寄存器传参,而是通过stack进行传参,所以go的反汇编不像c的那么容易理解,不过大概看懂+背后的操作还是没问题的,看一下runtime源码的拼接函数:

分析runtime的concatstrings实现,可以看出+最后新申请buf,拷贝原来的string到buf,最后返回新实例。那么每次的+操作,都会涉及新申请buf,然后是对应的copy。如果反复使用+,就不可避免有大量的申请内存操作,对于大量的拼接,性能就会受到影响了。

bytes.buffer

通过看源码,bytes.buffer 增长buffer时是按照2倍来增长内存,可以有效避免频繁的申请内存,通过一个例子来看:

对应的byte包库函数源码

string.join

这个函数可以一次申请最终string的大小,但是使用得预先准备好所有string,这种场景也是高效的,一个例子:

对应库的源码:

strings.builder (go1.10+)

看到这个名字,就想到了java的库,哈哈,这个builder用起来是最方便的,不过是在1.10后引入的。其高效也是体现在2倍速的内存增长, writestring函数利用了slice类型对应append函数的2倍速增长。

一个例子:

对应库的源码

总结

golang的字符串处理还是挺方便的,有垃圾回收和一些内置的语言级写法支持,让复杂字符串操作没有那么繁琐了,比起c/c++高效了不少。

补充:go string的内部实现

go string 内部实现

这个string的探索

来来个例子

其中

其实可以看到string就是c里面的char* 和len的组合

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。

相关标签: Go string 底层