我见过人们使用unsafe.Pointer
有效地将[]byte
转换为string
https://play.golang.org/p/uz84H54VM8。
var b = []byte{'f', 'o', 'o', 'b', 'a', 'r'}
var s = *(*string)(unsafe.Pointer(&b))
我了解它在做什么以及所涉及的危险,但对记忆有疑问。
由于切片的结构具有数据指针、长度和容量,但字符串没有容量,因此如果在堆上创建了b
,该内存会发生什么情况?垃圾回收器是否知道它需要单独跟踪容量?或者这可能会导致内存泄漏?
编辑:
我了解如何重新切片字符串和切片。上面的代码适用于您需要从[]byte
转换为string
但又想避免完整复制的情况。
问题是关于我们从结构中删除的capacity
以及它是否会导致 GC 问题。
语句var s = *(*string)(unsafe.Pointer(&b))
将数据和长度从切片标头值复制到字符串标头值。
该语句不会更改运行时对切片标头的解释。容量不会从切片标题中删除。
仅复制数据和长度不会导致 GC 问题。
- 字符串标头和切片标头值在复制操作后均有效。
- 垃圾回收器不假定字符串支持数组的大小等于字符串标头中的长度。例如,GC 处理安全代码
s := "foobarxxx"[:6]
其中字符串标头s
的长度为 6,后备数组的大小为 9。