开发中经常会遇到将一个字符串转换成byte数组的操作,考虑到String类型的不可修改,如何高效进行String到byte数组的切换就显得尤为重要。
0x1 原理
String
类型在运行时被转换成StringHeader
类型,其底层实现如下所示:
// StringHeader is the runtime representation of a string.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type StringHeader struct {
Data uintptr
Len int
}
Slice
类型在运行时的结构如下所示:
// SliceHeader is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
可以通过指针操作,修改其Cap
字段的值。
具体代码如下:
// StringToBytes converts string to a byte slice without memory allocation.
func Str2Byte(s string) (b []byte) {
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
return b
}
// BytesToString converts byte slice to a string without memory allocation.
func BytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}