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))
取消引用字符串頭指針以獲取字符串。此操作將數據和長度字段從切片標頭復制到字符串標頭。
如果對切片頭字段重新排序而沒有對字符串頭字段進行相應更改,則此代碼將中斷,但這永遠不會發生。
- 1 回答
- 0 關注
- 111 瀏覽
添加回答
舉報
0/150
提交
取消