我们将string
转换为[]byte
:
func toBytes(s string) []byte {
return []byte(s) // What happens here?
}
这次施法操作有多贵?正在进行复制吗?就我在Go规范中看到的那样:字符串的行为类似于字节切片但是是不可变的,这至少应该涉及复制以确保后续的切片操作不会修改我们的字符串s
。反向对话会发生什么? []byte <-> string
会话是否涉及编码/解码,例如utf8&lt; - &gt;符?
答案 0 :(得分:25)
[]byte(s)
不是演员,而是conversion。某些转换与转换相同,例如uint(myIntvar)
,它只是重新解释位位。不幸的是,这不是字符串到字节切片转换的情况。字节切片是可变的,字符串(字符串值要精确)不是。结果是正在进行的字符串的必要副本(mem alloc + content transfer)。所以是的,在某些情况下它可能会很昂贵。
编辑:不执行编码转换。字符串(源)字节按原样复制到切片(目标)字节。
答案 1 :(得分:11)
转换复制字节,但它也为堆上的[]字节分配空间。如果重复将字符串转换为[]字节,则可以通过重用[]字节并使用copy命令来节省内存管理时间。 (参见http://golang.org/ref/spec#Appending_and_copying_slices以及关于使用字符串作为来源的特殊情况。)
在转换和复制命令的两种情况下,副本本身都是一个直接的字节副本,它应该运行得非常快。我希望编译器能够生成某种有效执行的重复移动指令。
反向转换,从字节切片中生成一个字符串,肯定涉及在堆上分配字符串。不变性财产迫使这一点。有时您可以通过[]字节尽可能多地完成工作来优化,然后在最后创建一个字符串。 bytes.Buffer类型通常很有用。
现在追逐红鲱鱼,编码和UTF-8不是问题。字符串和[]字节都可以保存任意数据。副本不会查看数据,只是复制它。当说字符串意图以包含UTF-8或鼓励时,请仔细选择单词。简单地注意一些语言特性(例如for语句的range子句,将字符串解释为UTF-8)更准确。只需了解将字符串解释为UTF-8的内容,以及什么不是。在字符串中使用非UTF-8并且需要按字节顺序排列吗?没问题,只是不要使用范围条款。
s := "string"
for i := 0; i < len(s); i++ {
b := s[i]
// work with b
}
这是惯用的Go。它并没有气馁,也没有任何意图。它只是按字节顺序遍历字符串,这有时就是你想要做的事情。