题目:字符串转byte数组时,是否会发生内存拷贝?
解析:字符串转切片一定会产生内存拷贝,严格来说,只要是发生数据类型转换都会发生内存拷贝。
到这里上述问题就解释完事儿了,那接下来就有新的问题了,因为频繁的内存拷贝听起来对于性能来说不是很友好,那就要想想有没有什么办法使得字符串在转切片的时候不发生内存拷贝呢?
来看如下代码:
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
a := "aaa"
ssh := *(*reflect.StringHeader)(unsafe.Pointer(&a))
b := *(*[]byte)(unsafe.Pointer(&ssh))
fmt.Printf("%v", b)
}
StringHeader是字符串在Go的底层数据结构:
type StringHeader struct {
Data uintptr
Len int
}
SliceHeader是切片在G的底层数据结构:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
如果我们想要在底层实现StringHeader和SliceHeader的互转,只需要把StringHeader的地址强制转换为SliceHeader就可以。
Go的unsafe包实现了上述功能,来看下介绍:
-
unsafe.Pointer(&a) 方法可以得到变量a的指针地址。
-
(*reflect.StringHeader)(unsafe.Pointer(&a)) 可把字符串a转成底层结构形式。
-
(*[]byte)(unsafe.Pointer(&ssh)) 可把ssh底层结构体转成byte的切片的指针。
-
再通过* 转为指针指向的实际内容。
扫码关注公众号,获取更多优质内容。