这是一个非常精典的例子。实现字符串和 bytes 切片之间的转换,要求是 zero-copy。想一下,一般的做法,都需要遍历字符串或 bytes 切片,再挨个赋值。

    完成这个任务,我们需要了解 slice 和 string 的底层数据结构:

    1. type StringHeader struct {
    2. Data uintptr
    3. Len int
    4. }
    5. type SliceHeader struct {
    6. Data uintptr
    7. Len int
    8. Cap int
    9. }

    上面是反射包下的结构体,路径:src/reflect/value.go。只需要共享底层 []byte 数组就可以实现 zero-copy

    1. func string2bytes(s string) []byte {
    2. stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
    3. bh := reflect.SliceHeader{
    4. Data: stringHeader.Data,
    5. Len: stringHeader.Len,
    6. Cap: stringHeader.Len,
    7. }
    8. return *(*[]byte)(unsafe.Pointer(&bh))
    9. }
    10. func bytes2string(b []byte) string{
    11. sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    12. sh := reflect.StringHeader{
    13. Data: sliceHeader.Data,
    14. Len: sliceHeader.Len,
    15. }
    16. return *(*string)(unsafe.Pointer(&sh))
    17. }

    代码比较简单,不作详细解释。通过构造 slice header 和 string header,来完成 string 和 byte slice 之间的转换。