背景
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))
}
参考
PREVIOUSPostgres使用PgAudit获取审计日志
NEXTrust编译时注入编译信息