根据这篇Go Data Structures文章,在 Strings 部分下,它指出采取一个字符串片段会将原始字符串保留在内存中。
“(另外,在Java和其他语言中有一个众所周知的问题,当你切割一个字符串以保存一小块时,对原始文件的引用会将整个原始字符串保留在内存中,即使只有少量仍然需要.Go也有这个问题。我们尝试和拒绝的替代方案是使字符串切片如此昂贵 - 分配和副本 - 大多数程序都避免它。)“ < / p>
所以如果我们有一个很长的字符串:
s := "Some very long string..."
我们采取一小部分:
newS := s[5:9]
在我们发布s
之前,我们不会发布原始newS
。考虑到这一点,如果我们需要保持newS
长期,但释放s
进行垃圾收集,采取什么方法?
我想也许这样:
newS := string([]byte(s[5:9]))
但我不确定这是否真的有用,或者是否有更好的方法。
答案 0 :(得分:5)
是的,转换为一个字节片段将创建一个字符串的副本,因此原始字符串不再被引用,并且可以在某个地方进行GC。
作为这个的“证明”(好吧,它证明了字节切片不与原始字符串共享相同的底层数据):
http://play.golang.org/p/pwGrlETibj
编辑:并证明字节片只有必要的长度和容量(换句话说,它的容量不等于原始字符串的容量):
http://play.golang.org/p/3pwZtCgtWv
Edit2:你可以清楚地看到内存分析会发生什么。在reuseString()中,使用的内存非常稳定。在copyString()中,它会快速增长,显示由[]字节转换完成的字符串副本。
答案 1 :(得分:2)