IT袋

当前位置:主页 > 经验教程 > 建站编程 >

[]byte与string的两种转换方式和底层实现

[]byte与string的两种转换方式和底层实现(3)

时间:2024-03-25 20:24:26 来源:IT袋 作者:马勇
导读:[]byte与string的两种转换方式和底层实现,跟string转[]byte一样,当数组长度超过32时,同样需要调用mallocgc分配一块新内存 强转换底层实现 从标准的转换方式中,我们知道如果字符串长度超过32的话

[]byte与string的两种转换方式和底层实现

跟string转[]byte一样,当数组长度超过32时,同样需要调用mallocgc分配一块新内存

强转换底层实现

从标准的转换方式中,我们知道如果字符串长度超过32的话,会重新分配一块新内存,进行内存拷贝。

//string转[]byte
func s2b(s string) (b []byte) {
    bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
    bh.Data = sh.Data
    bh.Cap = sh.Len
    bh.Len = sh.Len
    return b
}

强转换过程中,通过 神奇的unsafe.Pointer指针

  • •任何类型的指针 *T 都可以转换为unsafe.Pointer类型的指针,可以存储任何变量的地址
  • •unsafe.Pointer 类型的指针也可以转换回普通指针,并且可以和类型*T不相同

refletc包的 reflect.SliceHeader 和 reflect.StringHeader分别代表什么意思?

reflect.SliceHeader:slice类型的运行时表示形式

reflect.StringHeader:string类型的运行时表示形式

//slice在运行时的描述符
type SliceHeader struct {      
     Data uintptr
     Len  int
    Cap  int
}
//string在运行时的描述符
type StringHeader struct {
    Data uintptr
    Len  int
}

*(reflect.SliceHeader)(unsafe.Pointer(&b))的目的就是通过unsafe.Pointer 把它们转换为 *reflect.SliceHeader 指针。

而运行时表现形式 SliceHeader 和 StringHeader,而这两个结构体都有一个 Data 字段,用于存放指向真实内容的指针。

[]byte 和 string之间的转换,就可以理解为是通过 unsafe.Pointer 把 *SliceHeader 转为 *StringHeader,也就是 *[]byte 和 *string之间的转换。

那么我们就可以理解相对于标准转换方式,强转换方式的优点在哪了!

直接替换指针的指向,避免了申请新内存(零拷贝),因为两者指向的底层字段Data地址相同

总结

今天不念和大家一起了解了[]byte和string类型,以及[]byte和string的两种转换方式。

不过Go语言提供给我们使用的还是标准转换方式,主要是因为在你不确定安全隐患的情况下,使用强转化方式可能不必要的问题。

不过像fasthttp那样,对程序对运行性能有高要求,那就可以考虑使用强转换方式!

以上就是[]byte与string的两种转换方式和底层实现的全面方法讲解,希望为您起一个抛砖引玉袋作用,能解决您生活中的问题吧。

相关阅读