在[] byte和string之间进行转换时,Go 1.6编译器应用哪些优化,反之亦然?

yak*_*ori 4 type-conversion go

我知道从[]字节转换为字符串,反之亦然,会导致生成基础数组的副本.从字符串不可变的角度来看,这对我来说很有意义.

然后我在这里读到在特定情况下编译器会做出两个优化:

"当[]字节键用于查找map [string]集合中的条目时,第一个优化避免了额外的分配:m [string(key)]."

这是有道理的,因为转换仅限于方括号,因此没有在那里改变字符串的风险.

"第二个优化避免了对于将字符串转换为[]字节的范围子句的额外分配:对于i,v:= range [] byte(str){...}."

这是有道理的,因为再一次 - 没有办法在这里改变字符串.

还提到了todo列表的进一步优化(不确定哪个todo列表被引用),所以我的问题是:

Go 1.6中是否存在任何其他此类(进一步)优化,如果存在,那么它们是什么?

Hai*_*ile 7

[] byte to string

对于[]bytestring转化,编译器生成的内部呼叫runtime.slicebytetostringtmp功能(链接到源),当它可以证明

在调用goroutine可能修改原始切片或与另一个goroutine同步之前,将丢弃字符串形式.

runtime.slicebytetostringtmp返回string引用实际[]byte字节,因此不分配.功能中的评论说

// First such case is a m[string(k)] lookup where
// m is a string-keyed map and k is a []byte.
// Second such case is "<"+string(b)+">" concatenation where b is []byte.
// Third such case is string(b)=="foo" comparison where b is []byte.
Run Code Online (Sandbox Code Playgroud)

简而言之,对于b []byte:

  • 地图查找m[string(b)]不分配
  • "<"+string(b)+"> 连接不分配
  • string(b)=="foo" 比较不分配

第二个优化是在2015年1月22日实施的,它在go1.6中

第三个优化是在2015年1月27日实施的,它在go1.6中

因此,例如,在以下内容中:

var bs []byte = []byte{104, 97, 108, 108, 111}

func main() {
    x := string(bs) == "hello"
    println(x)
}
Run Code Online (Sandbox Code Playgroud)

比较不会导致go1.6中的分配.

字符串到[]字节

同样,runtime.stringtoslicebytetmp函数(链接到源)说:

// Return a slice referring to the actual string bytes.
// This is only for use by internal compiler optimizations
// that know that the slice won't be mutated.
// The only such case today is:
// for i, c := range []byte(str)
Run Code Online (Sandbox Code Playgroud)

所以i, c := range []byte(str)不分配,但你已经知道了.