为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 Golang string.Builder String() 可以在没有

为什么 Golang string.Builder String() 可以在没有

Go
陪伴而非守候 2022-10-24 15:37:04
Go 的 strings 包定义了一个 Builder 类型,它有一个 String() 方法func (b *Builder) String() string {    return *(*string)(unsafe.Pointer(&b.buf))}正如 reflect pacakge 所指出的,一个字节切片被定义为一个 SliceHeader 和一个由 header 的 Data 字段指向的关联数据块:type SliceHeader struct {  Data uintptr  Len  int  Cap  int}并且 string 被定义为一个 StringHeader 和一个由 header 的 Data 字段指向的关联数据块type StringHeader struct {  Data uintptr  Len  int}SliceHeader 有 3 个字段(Data、Len 和 Cap),而 StringHeader 只有 2 个(Data 和 Len),那么如何直接将字节切片转换为字符串呢?*(*string)(unsafe.Pointer(&buf))据我了解,我们应该编写以下代码:func byte2str(b []byte) string {  hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))  return *(*string)(unsafe.Pointer(&reflect.StringHeader{Data: hdr.Data, Len: hdr.Len}))}
查看完整描述

1 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

让我们分解一下。

表达式&buf是指向切片头的指针。指向切片的指针是指向切片头的指针。

该表达式(unsafe.Pointer(&buf)是从切片头指针到unsafe.Pointer. unsafe.Pointer 类型有一个神奇的属性——它可以与任何其他指针类型相互转换。

表达式是(*string)(unsafe.Pointer(&buf))从切片头指针到字符串头指针的转换。指向字符串的指针是指向标头的指针。

此时,我们有一个字符串头指针,它实际上指向一个切片头。乍一看,这似乎很糟糕,但一切都很好。字符串头的内存布局是切片头的内存布局的前缀。

该表达式*(*string)(unsafe.Pointer(&buf))取消引用字符串头指针以获取字符串。此操作将数据和长度字段从切片标头复制到字符串标头。

如果对切片头字段重新排序而没有对字符串头字段进行相应更改,则此代码将中断,但这永远不会发生。


查看完整回答
反对 回复 2022-10-24
  • 1 回答
  • 0 关注
  • 175 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号