[]byte(string) 有多贵?
Posted
技术标签:
【中文标题】[]byte(string) 有多贵?【英文标题】:How expensive is []byte(string)? 【发布时间】:2012-12-31 16:05:41 【问题描述】:让我们将string
转换为[]byte
:
func toBytes(s string) []byte
return []byte(s) // What happens here?
这种演员阵容有多贵?是否执行复制?据我在 Go 规范中看到的:字符串的行为类似于字节切片,但不可变,这至少应该涉及复制,以确保后续切片操作不会修改我们的字符串 s
。反向对话会发生什么? []byte <-> string
对话是否涉及编码/解码,如 utf8 runes?
【问题讨论】:
我已经编写了一个基准here,概述了性能影响。 【参考方案1】:[]byte(s)
不是演员表,而是conversion。一些转换与强制转换相同,例如uint(myIntvar)
,它只是重新解释位就地。不幸的是,字符串到字节切片转换的情况并非如此。字节切片是可变的,字符串(准确地说是字符串值)不是。结果是正在制作的字符串的必要副本(内存分配+内容传输)。所以是的,在某些情况下它可能会很昂贵。
编辑:不执行编码转换。字符串(源)字节按原样复制到切片(目标)字节。
【讨论】:
string
内部如何存储不是很清楚,是 utf8 还是 rune?你能说说这个吗?
来自golang.org/ref/spec#String_types:“字符串的元素具有字节类型,可以使用通常的索引操作进行访问。”。所以没有 UTF-8,没有符文。 String 是一个编号的字节序列,any 个字节。 OTOH,许多 stdlib 函数仅适用于 UTF-8 编码的字符串。
@demi 字符串的表示是一种字节数组。但是,字符串显然旨在包含 utf-8 编码:应用于字符串的 range
语句解码 utf-8 并返回代码点。 See here in the spec.
"Programming in Go" 一书声称:“[]byte(string)
的转换速度非常快 (O(1)),因为在后台,@ 987654330@ 可以简单地引用字符串的底层字节,不需要复制。反向转换也是如此,string([]byte);
再次没有复制底层字节,所以转换是 O(1)。" 所以看来这种说法是不正确的。
FWIW,有一个 open issue 请求一个功能,如果在 []byte(s)
转换后生成的字节数组从未被修改,它将使用字符串提供的底层数组而不是复制。从表面上看,这似乎是一个有用的优化。【参考方案2】:
转换复制字节,但它也为堆上的 []byte 分配空间。在将字符串反复转换为 []byte 的情况下,您可以通过重用 []byte 和使用 copy 命令来节省内存管理时间。 (参见http://golang.org/ref/spec#Appending_and_copying_slices 以及使用字符串作为源的特殊情况。)
在转换和复制命令的两种情况下,复制本身都是一个直字节复制,它应该运行得非常快。我希望编译器能够生成某种 CPU 高效执行的重复移动指令。
逆向转换,从字节片中生成字符串,肯定涉及在堆上分配字符串。不变性属性迫使这一点。有时您可以通过使用 []byte 做尽可能多的工作然后在最后创建一个字符串来进行优化。 bytes.Buffer 类型通常很有用。
现在追逐红鲱鱼,编码和 UTF-8 都不是问题。字符串和 []byte 都可以保存任意数据。副本不查看数据,它只是复制它。在说诸如字符串打算包含 UTF-8 或 鼓励这样的内容时,请谨慎选择词语。更准确的做法是简单地注意一些语言特性,例如 for 语句的范围子句,解释字符串为 UTF-8。只需了解将字符串解释为 UTF-8 和不解释的内容。字符串中有非 UTF-8 并且需要按字节进行范围?没问题,只是不要使用范围子句。
s := "string"
for i := 0; i < len(s); i++
b := s[i]
// work with b
这是惯用的 Go。它没有气馁,也没有违反任何意图。它只是逐字节迭代字符串,这有时正是您想要做的。
【讨论】:
【参考方案3】:作为对上述答案的补充,在最新的go language specification中,string
与数字类型之间的类型转换的特殊规则声明如下:
特定规则适用于数字类型之间或字符串类型之间的(非常量)转换。这些转换可能会改变 x 的表示并产生运行时成本。所有其他转换只改变 x 的类型,但不改变 x 的表示。
【讨论】:
以上是关于[]byte(string) 有多贵?的主要内容,如果未能解决你的问题,请参考以下文章