在我们的程序里面基本都写成如下的转换
var a = []byte("hello world")
var b = string(a)
这样的强制类型转换其实是调用底层的copy 函数进行转化,也就是说需要在内存中进行拷贝。这如果并发量达到千万级别,这样的转换是很耗性能的。
那么我们是否可以使用 unsafe.Point() 这样的指针直接转换呢?首先我们的知道 string 和 []byte 的底层表示方式。
string 的底层数组结构如下
struct string {
unit8 *str
int len
}
而 []byte 的底层结构如下
struct uint8 {
unit8 *array
int len
int cap
}
通过对比 string 和 []byte 的结构体可知,[]byte 转换成 string 是可以直接使用 unsafe.Point(&b) 这样直接转换的。而string 则不可以直接转换成 []byte。 而需要构造把 string 的 str 指针赋值给 array 指针,把string 的 len 赋值给 []byte 的 len 和 cap.
高效的转换方法:
func bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s)) // 获取s的起始地址开始后的两个 uintptr 指针
h := [3]uintptr{x[0], x[1], x[1]} // 构造三个指针数组
return *(*[]byte)(unsafe.Pointer(&h))
}