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

Go语言的核心特性包括垃圾回收、静态链接和并发支持。1.Go语言的并发模型通过goroutine和channel实现高效并发编程。2.接口和多态性通过实现接口方法,使得不同类型可以统一处理。3.基本用法展示了函数定义和调用的高效性。4.高级用法中,切片提供了动态调整大小的强大功能。5.常见错误如竞态条件可以通过gotest-race检测并解决。6.性能优化通过sync.Pool重用对象,减少垃圾回收压力。

Go语言在构建高效且可扩展的系统中表现出色,其优势包括:1.高性能:编译成机器码,运行速度快;2.并发编程:通过goroutines和channels简化多任务处理;3.简洁性:语法简洁,降低学习和维护成本;4.跨平台:支持跨平台编译,方便部署。

关于SQL查询结果排序的疑惑学习SQL的过程中,常常会遇到一些令人困惑的问题。最近,笔者在阅读《MICK-SQL基础�...

golang ...

Go语言中如何对比并处理三个结构体在Go语言编程中,有时需要对比两个结构体的差异,并将这些差异应用到第�...

GoLand中自定义结构体标签不显示怎么办?在使用GoLand进行Go语言开发时,很多开发者会遇到自定义结构体标签在�...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

Atom编辑器mac版下载
最流行的的开源编辑器

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 Linux新版
SublimeText3 Linux最新版

SublimeText3汉化版
中文版,非常好用