Go语言 如何在rpcx lib中理解StringToSliceByte?

ff29svar  于 2023-06-19  发布在  Go
关注(0)|答案(2)|浏览(86)

下面的代码片段来自rpcx库。

func StringToSliceByte(s string) []byte {
    x := (*[2]uintptr)(unsafe.Pointer(&s))
    h := [3]uintptr{x[0], x[1], x[1]}
    return *(*[]byte)(unsafe.Pointer(&h))
}

该代码用于有效地将字符串转换为字节片,但它是如何工作的呢?有人能对这段代码做一个全面的分析吗?
顺便说一下,还有一个更简洁的实现:

func toBytes(s string) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

下面的代码也可以工作:

func StringToSliceByte(s string) []byte {
    x := (*[1]int8)(unsafe.Pointer(&s))
    return *(*[]byte)(unsafe.Pointer(&x[0]))
}
w6mmgewl

w6mmgewl1#

从go1.20开始,您可以更安全地执行以下操作:

func StringToSliceByte(s string) []byte {
    return unsafe.Slice(unsafe.StringData(s), len(s))
}
xu3bshqb

xu3bshqb2#

一个字符串包含一个指向包含字符串数据和字符串长度的基础数组的指针。切片包含指向底层数组的指针、长度和切片的容量。
线路:

x := (*[2]uintptr)(unsafe.Pointer(&s))

访问字符串s的内部表示。
任务:

h := [3]uintptr{x[0], x[1], x[1]}

创建一个指向sx[0])的底层数组的切片h,长度和容量等于字符串长度第x[1]
然后将其作为切片返回。
unsafe的使用中可以看出,这是一段不安全的代码,它可能无法在以后的Go版本中工作。它依赖于数据类型的内部表示。它还违反了Go语言中字符串不可变的事实,因为它将字符串的底层数组作为切片返回。这是一种通过牺牲类型安全和语言假设来防止复制的优化。避开它。

相关问题