首頁 > 後端開發 > Golang > 如何在不使用'unsafe”複製的情況下從 Go 字串中獲取位元組切片?

如何在不使用'unsafe”複製的情況下從 Go 字串中獲取位元組切片?

Barbara Streisand
發布: 2024-11-01 01:51:28
原創
925 人瀏覽過

How to Obtain a Byte Slice from a Go String without Copying Using `unsafe`?

使用Unsafe 從字串中取得位元組切片而不進行複製

Go 字串是不可變的,這意味著將它們轉換為位元組切片涉及記憶體複製。這可能會影響處理大型資料集時的效能。本文探討如何使用 unsafe 來避免這種複製操作,同時強調關鍵面向和限制。

背景

標準函式 []byte(s) 建立字串 s 的副本。如果記憶體消耗是一個問題,那麼希望在不產生此開銷的情況下獲取位元組切片。

不安全轉換

利用不安全套件提供了實現此目標的方法。透過將字串值轉換為指向位元組數組的指針,我們可以存取底層位元組切片,而無需建立副本。

<code class="go">func unsafeGetBytes(s string) []byte {
    return (*[0x7fff0000]byte)(unsafe.Pointer(
        (*reflect.StringHeader)(unsafe.Pointer(&s)).Data),
    )[:len(s):len(s)]
}</code>
登入後複製

注意事項

值得注意的是,這種方法存在固有風險。 Go 中的字串是不可變的,因此修改透過 unsafeGetBytes 取得的位元組切片可能會導致意外行為甚至資料損壞。因此,此技術應僅在記憶體效能至關重要的受控內部環境中使用。

處理空字串

請注意,空字串(「」)沒有位元組,因此其資料欄位是不確定的。如果您的程式碼可能遇到空字串,則必須明確檢查它們。

<code class="go">func unsafeGetBytes(s string) []byte {
    if s == "" {
        return nil // or []byte{}
    }
    return (*[0x7fff0000]byte)(unsafe.Pointer(
        (*reflect.StringHeader)(unsafe.Pointer(&s)).Data),
    )[:len(s):len(s)]
}</code>
登入後複製

效能注意事項

雖然此轉換避免了複製的開銷,但必須記住壓縮操作(例如您提到的使用 gzipWriter 的操作)是計算密集型的。與壓縮所需的計算相比,避免記憶體複製帶來的潛在效能提升可能可以忽略不計。

替代方法

或者,可以利用 io.WriteString 函數將字串寫入 io .Writer無需呼叫複製操作。該函數檢查 io.Writer 上是否存在 WriteString 方法,並在可用時呼叫它。

相關問題和資源

進一步探索,請考慮以下資源:

  • [Go GitHub 問題25484](https://github.com/golang /go/issues/25484)
  • [unsafe.String](https://pkg.go.dev/不安全#String)
  • [unsafe.StringData](https:// pkg.go.dev/unsafe#StringData)
  • [[]byte(string) vs []byte(*string) )](https://stackoverflow.com/questions/23369632/)
  • [在go 中使用從[]byte 到字串的不安全轉換可能會產生什麼後果? ](https://stackoverflow.com /問題/67306718/)

以上是如何在不使用'unsafe”複製的情況下從 Go 字串中獲取位元組切片?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板