首頁  >  文章  >  後端開發  >  如何在Go中有效地使用指標來提高記憶體效率,同時避免資料結構中的記憶體洩漏?

如何在Go中有效地使用指標來提高記憶體效率,同時避免資料結構中的記憶體洩漏?

Patricia Arquette
Patricia Arquette原創
2024-10-28 10:02:02991瀏覽

How to effectively use pointers in Go for memory efficiency while avoiding memory leaks in data structures?

Go 中的垃圾收集和指針的正確使用

指針的背景

Go 中,指針用於引用存儲在內存中的數據,而不需要複製資料本身。這可以提高效能和記憶體效率,特別是在處理大型或複雜的資料結構時。

問題

提供的程式碼旨在建立一個將標籤對應到圖片 URL 清單的資料結構。然而,最初的設計考慮使用指標來節省內存,這引發了關於最終分配內存清理的問題。

問題回應

版本1:

  • 使用指向URL 欄位的指標會導致內存,因為指標仍引用底層字串數據。
  • 完整的 Image 結構及其所有欄位將保留在記憶體中因為儲存在 tagToUrlMap 中的任何指標都指向它們。

版本2:

  • 建立一個中間變數來保存URL 字串並使用指向它的指標解決了版本1 所引起的記憶體洩漏問題。
  • 但是,它引入了額外的間接和複雜性,並且不會顯著節省記憶體。

最佳解決方案

儲存 URL 最有效的方法是直接使用字串值,而不使用指標。 Go 已經透過使用字串池儲存字串來最佳化字串處理,這允許對同一字串的多個引用共享單一記憶體分配。

用於內存保護的字符串實習

為了進一步節省內存,代碼可以使用字符串駐留。它涉及僅存儲字串的一個實例,並在遇到相同字串時引用它。

提供的程式碼包括一個簡單的字串駐留函數(interned()),該函數使用快取來儲存和重複使用先前遇到的字串.

修正的程式碼

<code class="go">package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type Image struct {
    URL string
    Description string
    Tags []Tag
}

type Tag struct {
    Name string
    Rank int
}

func searchImages() []*Image {
    parsedJSON := []*Image{
        &Image{
            URL: "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg",
            Description: "Ocean islands",
            Tags: []Tag{
                Tag{"ocean", 1},
                Tag{"water", 2},
                Tag{"blue", 3},
                Tag{"forest", 4},
            },
        },
        &Image{
            URL: "https://c3.staticflickr.com/1/48/164626048_edeca27ed7_o.jpg",
            Description: "Bridge over river",
            Tags: []Tag{
                Tag{"bridge", 1},
                Tag{"river", 2},
                Tag{"water", 3},
                Tag{"forest", 4},
            },
        },
    }
    return parsedJSON
}

func interned(s string) string {
    if str, ok := cache[s]; ok {
        return str
    }
    cache[s] = s
    return s
}

var cache = make(map[string]string)

func main() {
    result := searchImages()

    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)
        }
    }

    // Clear the interner cache
    cache = nil

    // Trim allocated slices to the minimum needed
    for tagName, urls := range tagToUrlMap {
        if cap(urls) > len(urls) {
            urls2 := make([]string, len(urls))
            copy(urls2, urls)
            tagToUrlMap[tagName] = urls2
        }
    }

    enc := json.NewEncoder(os.Stdout)
    enc.SetIndent("", "  ")
    if err := enc.Encode(tagToUrlMap); err != nil {
        panic(err)
    }
}</code>

其他資源

  • [並發不是並行](https://blog.golang.org/go-nuts)
  • [了解Go 中的內存管理](https://blog.gopheracademy.com/advent-2016/understanding-memory-management-in-go/)
  • [Go 中的垃圾收集](https://www.golang- book.com/books/intro/12)
  • [stringsx.Pool](https://github.com/icza/gox)(Go 庫,提供字串池)

以上是如何在Go中有效地使用指標來提高記憶體效率,同時避免資料結構中的記憶體洩漏?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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