golang中进行类型转换时避免GC产生

 

背景

golang为了简洁性和易用性,在一些常用的使用方式上是有一定的性能损耗的。
例如将一个函数从[]byte转换成string,这个是一个很常见的需求,比如我们需要读取一个文件的内容并保存成一个字符串:

buf, err := os.ReadFile("file.txt")
if err != nil {
    panic(err)
}
res := string(buf)

上述代码在将结果从[]byte转换成string时,是会进行内存分配和拷贝的,因此就会涉及到了GC。积少成多,也是会一定程度影响程序的性能的。
因此需要考虑,有没有一种重新解释(reinterpret cast)的方法,直接将[]byte转换成string,而避免中间过程的内存操作呢?

做法

以下提供几种做法,具体安全性和正确性见仁见智了:

func Bytes2String(bytes []byte) (s string) {
    slice := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
    str := (*reflect.StringHeader)(unsafe.Pointer(&s))
    str.Data = slice.Data
    str.Len = slice.Len
    runtime.KeepAlive(&bytes)
}
func Bytes2String(bytes []byte) string {
    return *(*string)(unsafe.Pointer(&bytes))
}
func Bytes2String(bytes []byte) string {
   x := (*[3]uintptr)(unsafe.Pointer(&bytes))
   s := [2]uintptr{x[0], x[1]}
   return *(*string)(unsafe.Pointer(&s))
}

参考