首頁  >  文章  >  後端開發  >  在 Go 中使用指標和垃圾收集時,如何有效管理記憶體使用並防止垃圾創建?

在 Go 中使用指標和垃圾收集時,如何有效管理記憶體使用並防止垃圾創建?

Patricia Arquette
Patricia Arquette原創
2024-10-31 18:36:02832瀏覽

How can I effectively manage memory usage and prevent garbage creation when working with pointers and garbage collection in Go?

Go 中的垃圾收集和指針:資料結構映射綜合指南

簡介

在Python、Ruby 和JavaScript 中,指針的工作方式不同比圍棋。 Go 的垃圾收集器會自動釋放內存,因此了解指標的使用情況以優化內存消耗並防止不必要的垃圾創建至關重要。

範例:將標籤對應到圖片 URL

考慮傳回一個虛構的 API具有相關標籤的圖片資料集。我們的目標是建立一個資料結構,將每個標籤對應到對應影像URL 的清單:

<code class="python">{
    "ocean": [
        "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg"
    ],
    "water": [
        "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg",
        "https://c3.staticflickr.com/1/48/164626048_edeca27ed7_o.jpg"
    ],
    ...
}</code>

使用指標(版本1)

表示此對應的一種方法是使用指標到影像結構的URL 欄位:

<code class="go">tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &image.URL)
    }
}</code>

結果:

  • 映像URL 字串欄位與結果資料結構一起儲存在記憶體中。
  • 結果資料結構一直保留在記憶體中,直到程式結束,因為它的成員被引用。

使用中間變數(版本2)

另一種方法是使用中間變數並儲存指向它的指標:

<code class="go">tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    imageUrl = image.URL
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &imageUrl)
    }
}</code>

結果:

  • 只有中間imageUrl 變數保留在記憶體中,而不是中間imageUrl 變數圖像URL 字串欄位。
  • 結果資料結構可以正確進行垃圾收集。

在影像結構中使用指向字串的指標

另一個選擇是使用指向Image 結構中字串的指標:

<code class="go">type Image struct {
    URL *string
    Description string
    Tags []*Tag
}</code>

注意事項:

  • 與其他方法相比,沒有額外的記憶體節省。
  • 增加了複雜性和間接性。

最佳解決方案:字串實習

記憶體效率的最佳解決方案是使用字串實習,這確保唯一字串值只有一個實例存在於記憶體中。

<code class="go">var cache = map[string]string{}

func interned(s string) string {
    if s2, ok := cache[s]; ok {
        return s2
    }
    cache[s] = s
    return s
}</code>

實作:

<code class="go">tagToUrlMap := make(map[string][]string)

for _, image := range result {
    imageURL := interned(image.URL)

    for _, tag := range image.Tags {
        tagName := interned(tag.Name)
        tagToUrlMap[tagName] = append(tagToUrlMap[tagName], imageURL)
    }
}</code>

結論

  • 字串值的作用類似於Go 中的指針,使得使用*字串不必要。
  • 如果儲存指向其成員的指針,結果資料結構將保留在記憶體中。
  • 應小心儲存欄位或陣列元素位址,以避免記憶體碎片。
  • 字串駐留是減少記憶體消耗的最佳解決方案。
  • 為了進一步最佳化,請從使用append()建立的切片中修剪多餘的容量。

以上是在 Go 中使用指標和垃圾收集時,如何有效管理記憶體使用並防止垃圾創建?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn