首页 > 后端开发 > Golang > 正文

如何在Go中有效地使用指针来提高内存效率,同时避免数据结构中的内存泄漏?

Patricia Arquette
发布: 2024-10-28 10:02:02
原创
982 人浏览过

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中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!