首页  >  文章  >  后端开发  >  在 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