在Golang中使用已知文本字符串创建一个字节切片

13

我有这段文字,希望将其放入一个字节切片中:

s := "There are these two young fish swimming along and they happen to meet an older fish swimming the other way"

如果我写

b := []byte("There are these two young fish swimming along and they happen to meet an older fish swimming the other way")

据我理解,在运行时,这将会:

  1. 创建一个包含内存中的值的字符串
  2. 创建一个字节切片
  3. 将字符串内容复制到字节切片中(必要时重新分配内存)

我可以将每个字符串值转换为其ASCII等效项并直接创建字节切片:

b := []byte{84, 104, ... }

虽然这不是很易读。

我知道这个例子有点琐碎,而且大多数计算机可以迅速完成这项工作,但我对此很感兴趣。编译器会解释[]byte("blah")并在编译时将其转换为高效的字节片吗?如果字符串包含非ASCII字符,最佳解决方案是否会改变?


1
这些转换是否是你最内部的计算循环的一部分?这是在性能分析中显示出来的瓶颈吗?GC是否缓慢,因为您通过这些转换生成了太多的垃圾?如果不是,请问为什么要费心呢? - Volker
“如果字符串包含非ASCII字符,最优解是否会改变?” 不会。Go源代码使用utf8;像for _, chr := range str {...}循环这样的东西处理utf8;您的程序可能不需要特别注意处理utf-8。 - twotwotwo
1
不要认为它会“根据需要重新分配”,因为它已经知道字符串中有多少字节,所以它可以一开始就抓取足够的内存。列出字节似乎是一个非常糟糕的想法(使您的源代码丑陋),我不确定它是否执行得更有效;由于字节切片是可变的,字节可能仍然需要从常量区域复制到堆内存。此外,正如Volker所说,启动时花费的任何纳秒都不是大问题。 - twotwotwo
Volker,因为我对这门语言还很陌生,所以我想知道实际上发生了什么。 - Kevin Burke
PeterSO的回答在这里看起来不错。Rob Pike在http://blog.golang.org/strings上有一篇关于Go字符串如何工作的很棒的文章,包括非ASCII字符。 - twotwotwo
2个回答

5

Go将字符串嵌入可执行程序中作为一个字符串字面量,使用runtime.stringtoslicebyte函数在运行时将字符串字面量转换为一个字节切片。


4
如果您正在从常量字符串初始化[]byte变量,那么编译器似乎足够聪明,不会创建中间字符串:相反,字节切片的支持数组直接从静态数据初始化,而不是首先构造字符串变量。
存在数据复制,但在构造可变类型时这是可以预料的。

在这里提供一个你看到的参考(基于“看起来像”)会很有帮助。 - seh
2
这是从检查编译器生成的汇编器中得出的。 - James Henstridge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接