当前位置: 首页 > news >正文

Go weak包前瞻:弱指针为内存管理带来新选择

在介绍Go 1.23引入的unique包的《Go unique包:突破字符串局限的通用值Interning技术实现》一文中,我们知道了unique包底层是基于internal/weak包实现的,internal/weak是一个弱指针功能的Go实现。所谓弱指针(Weak Pointer,也称为弱引用)是与强指针相对而言的,强指针(Strong Pointer,也可称作强引用)就是下面代码片段中的这种常规指针:

var p *T = new(T) // 假设T类型对象被分配到堆上

只要p指向堆上的T对象,那么T对象就无法被GC回收。但弱指针并非如此,它也可以指向堆上的某个内存对象(比如T类型对象),但它无法像强指针那样阻止GC回收该对象。

Go unique包的实现者Michael Knyszek近期提议在标准库引入weak包[3](实际上是将internal/weak公开暴露给Go开发者),该提议被Russ Cox代表的Go提案评审委员会所接受,最早将于Go 1.24版本落地。

在这篇短文中,我们来前瞻一下weak包的API设计、原理、应用场景以及社区对该提案一些观点。

注:weak包尚未落地,本文中的代码在Go 1.23中均无法运行,可以视作伪代码。

1. weak包的API

weak包的核心是Pointer[T]类型,它代表了对类型T的弱指针。以下目前Michael Knyszek为weak包设计的主要API:

type Pointer[T any] struct { ... }func Make[T any](ptr *T "T any") Pointer[T]func (p Pointer[T]) Value() *T

Make函数用于创建一个弱指针,而Value方法则用于获取弱指针指向的实际值。如果原始对象已被垃圾回收,Value方法将返回nil。这个设计秉承了Go一贯的简洁,允许开发者轻松创建和使用弱指针,同时保持了Go语言的类型安全特性。

2. weak包弱指针的工作原理

在开篇时,我已经对弱指针的作用做了简单说明,这里结合上述weak包的API和提案中的设计原理再扩展一下。

弱指针的核心思想是允许引用内存而不阻止垃圾回收器回收它。垃圾回收器在回收对象时,会自动将所有指向该对象的弱指针设置为nil。这确保了弱指针不会产生悬空引用(dangling pointer)。

下图是weak包弱指针的工作原理示意图,展示了weak pointer的核心工作原理,包括间接对象的使用和垃圾回收时的行为:

06dcb767757af0d4e1067e52bc9d44e8.png

简单看一下这张图:程序创建一个对象并通过weak.Make创建一个weak.Pointer(弱指针),在Go运行时内部,weak.Pointer通过8字节的间接对象引用原始对象。这个间接对象是weak.Pointer的内部字段,按当前internal/weak的实现来看,该字段是一个unsafe.Pointer。这个间接对象包含了实际的弱引用。

值得注意的是,弱指针的比较基于它们最初创建时使用的指针。即使原始对象被回收,两个由相同指针创建的弱指针仍然会被认为是相等的。这个特性使得弱指针可以安全地用作map的键。

3. weak包的典型使用场景

weak包的引入将为Go带来更灵活的内存管理机制,它允许开发者创建不会阻止垃圾回收的引用,从而在保持内存效率的同时,实现更复杂的数据结构和算法。特别是在处理缓存、规范化映射(Canonicalization mapping)[4]等场景时。

以缓存为例,使用弱指针,我们可以创建不会阻止被缓存对象被垃圾回收的缓存系统,这对于管理内存敏感的大型缓存系统特别有用。下面提案中Russ Cox举的一个使用weak包实现简单缓存的示例(可理解为伪代码):

type Cache[K any, V any] struct {f func(*K) Vm atomic.Map[uintptr, func() V]
}func NewCache[K comparable, V any](f func(*K "K comparable, V any")V) *Cache[K, V] {return &Cache[K, V]{f: f}
}func (c *Cache[K, V]) Get(k *K) V {kw := uintptr(unsafe.Pointer((k))vf, ok := c.m.Load(kw)if ok {return vf()}vf = sync.OnceValue(func() V { return c.f(k) })vf, loaded := c.m.LoadOrStore(kw, vf) // 原issue中似乎少了第二个参数vfif !loaded {// Stored kw→vf to c.m; add the cleanup.runtime.AddCleanup(k, c.cleanup, kw)}return vf()
}func (c *Cache[K, V]) cleanup(kw uintptr) {c.m.Delete(kw)
}var cached = NewCache(expensiveComputation)

这段代码定义了一个泛型缓存结构Cache,它有两个类型参数K和V,以及两个成员字段f和m:

  • f是一个函数,接受*K类型的指针,返回V类型的值,这是用于计算缓存值的函数。

  • m是一个原子映射,键是K类型的弱指针,值是返回V的函数。

NewCache是缓存的创建函数,接受一个计算函数f,返回初始化的Cache指针。

Cache类型的Get方法用于获取缓存的值,它首先创建键k的弱指针kw,然后以该弱指针为键尝试从缓存(atomicMap)中加载值。如果找到,直接返回缓存的值。如果未找到,使用sync.OnceValue创建一个只执行一次的函数,调用c.f(k)计算值。之后,尝试将新计算的函数存储到缓存中。如果成功存储(即之前没有这个键),添加一个清理函数,最后返回计算后的Value值。

这个实现允许缓存中的键在不再被程序其他部分引用时被垃圾回收,从而避免了内存长期占用或是泄漏。

4. 社区声音

针对该weak包提案,Go社区的主要声音是支持的,认为weak包将为Go带来更灵活的内存管理机制,但也表示了对无法用好weak包这个低级机制的担忧,希望在正式文档或Go Tour中包含更多使用关于weak包的示例和最佳实践。

Go新版GC的主要设计者Richard L. Hudson[5]提出了对sweeping storms和清理大型缓存中过时weak条目的担忧,并提出了使用ephemerons[6](一种更复杂的弱引用机制)的可能性,但也认识到其实现复杂度和性能开销较高。

也有一些Go社区开发者保持了对weak包的谨慎态度,比如fasthttp的维护者、VictorialMetrics[8]的联创Aliaksandr Valialkin[9] 就建议:在决定如何在Go中实现弱指针之前,最好先分析其他编程语言中弱指针的最常见的生产用例,并首先思考一下在标准库中为这些实际用例提供更高级别的解决方案而不是暴露较低级别的弱指针的方案是否会更好。

也有gopher提出:能否在提案中添加2-3个没有弱指针就无法解决的实际问题的例子,但Michael Knyszek并未回应。

5. 小结

weak包的引入让Go的工具箱更加完整,它为开发者提供了更细粒度的内存控制,同时其核心API也保持了Go简单易用的特性。

对于Go开发者来说,weak包使得某些复杂的内存管理场景变得更容易处理,但也需要开发者更好地理解垃圾回收机制和弱引用的工作原理。

社区对weak包的引入持积极态度,但也关注其实现细节、性能影响和最佳实践,同时也意识到了使用weak指针时可能面临的挑战。

不过,开发者在使用weak包时还是需要谨慎,毕竟过度使用弱指针可能会使代码变得难以理解和维护,最好的方法是将它用在最适合的场景下。


往期推荐

- Go unique包:突破字符串局限的通用值Interning技术实现

- Go 1.21中值得关注的几个变化

- Go GC如何检测内存对象中是否包含指针

- htmx:Gopher走向全栈的完美搭档?

- Go语言的“黑暗角落”:盘点学习Go语言时遇到的那些陷阱


Gopher部落知识星球[10]在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时,我们也会加强代码质量和最佳实践的分享,包括如何编写简洁、可读、可测试的Go代码。此外,我们还会加强星友之间的交流和互动。欢迎大家踊跃提问,分享心得,讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落,享受coding的快乐! 欢迎大家踊跃加入!

66432d0ea8e7a861debab90b05f55ffa.jpeg8a51067c8f05f2a1a23f625edd1e9a54.png

9659117770fbfcc114dc3b0371decae7.png9d1ccef2ba8b6b04630f86bc9a920d50.jpeg

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址[11]:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) - https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx

  • 微博2:https://weibo.com/u/6484441286

  • 博客:tonybai.com

  • github: https://github.com/bigwhite

  • Gopher Daily归档 - https://github.com/bigwhite/gopherdaily

  • Gopher Daily Feed订阅 - https://gopherdaily.tonybai.com/feed

5b2d209455bdd98fe13532e3c189493b.jpeg

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

参考资料

[1] 

Go 1.23: https://tonybai.com/2024/08/19/some-changes-in-go-1-23

[2] 

Go unique包:突破字符串局限的通用值Interning技术实现: https://tonybai.com/2024/09/18/understand-go-unique-package-by-example/

[3] 

Michael Knyszek近期提议在标准库引入weak包: https://github.com/golang/go/issues/67552

[4] 

规范化映射(Canonicalization mapping): https://wiki.c2.com/?CanonicalizedMapping

[5] 

Richard L. Hudson: https://github.com/RLH

[6] 

ephemerons: https://dl.acm.org/doi/pdf/10.1145/263698.263733

[7] 

fasthttp: https://tonybai.com/2021/04/25/server-side-performance-nethttp-vs-fasthttp

[8] 

VictorialMetrics: https://github.com/VictoriaMetrics/VictoriaMetrics

[9] 

Aliaksandr Valialkin: https://github.com/valyala

[10] 

Gopher部落知识星球: https://public.zsxq.com/groups/51284458844544

[11] 

链接地址: https://m.do.co/c/bff6eed92687

相关文章:

Go weak包前瞻:弱指针为内存管理带来新选择

在介绍Go 1.23引入的unique包的《Go unique包:突破字符串局限的通用值Interning技术实现》一文中,我们知道了unique包底层是基于internal/weak包实现的,internal/weak是一个弱指针功能的Go实现。所谓弱指针(Weak Pointer,也称为弱…...

ZStack AIOS平台智塔入选2024世界计算大会专题展优秀成果

9月24日至25日,由湖南省人民政府主办,湖南省工业和信息化厅、长沙市人民政府、中国电子信息产业发展研究院承办的2024世界计算大会在湖南长沙举办。云轴科技ZStack AIOS平台智塔凭借在智算领域的卓越表现,入选2024世界计算大会专题展优秀成果…...

总结 自行解决问题经验

一、总结在使用Linux时遇到的各种坑 yum 源要替换为国内源wget 需要用yum先行下载在make的时候需要预先安装各种库端口无法访问时要记得去防火墙开启端口访问权限安装完各种程序的时候记得创建环境变量或者软链接… 二、遇到故障如何正确高效的去解决 在使用yum下载wget的时…...

软件设计模式——工厂模式

软件设计模式——工厂模式 文章目录 软件设计模式——工厂模式一、设计模式的认知1.1 什么是软件设计模式:1.2 为什么要学习设计模式:1.3 设计模式的分类: 二、工厂模式2.1 工厂模式实例: 一、设计模式的认知 1.1 什么是软件设计…...

Apache Druid命令执行(CVE-2021-25646)

漏洞详情: Apache Druid 是用Java编写的面向列的开源分布式数据存储系统,旨在快速获取大量事件数据,并在数据之上提供低延迟查询。 Apache Druid含有能够执行嵌入在各种类型请求中由用户提供的JavaScript代码功能。此功能适用于高度信任环境…...

新的 MathWorks 硬件支持包支持从 MATLAB 和 Simulink 模型到高通 Hexagon 神经处理单元架构的自动化代码生成

MathWorks 今天宣布,推出针对 Qualcomm Hexagon™ 神经处理单元(NPU)的硬件支持包。该处理单元嵌入在 Snapdragon 系列处理器中。MathWorks 硬件支持包,则专门针对 Qualcomm Technologies 的 Hexagon NPU 架构进行优化&#xff0c…...

gorm.io/sharding:改造,当查询条件中不包含分表键时,从自定义方法中获取对应的表进行查询

项目背景 这篇文章是一种特殊的情形——当查询条件中不包含分表键时,从自定义方法中获取对应的表进行查询。实际项目中并不建议这种用法。 当然,这里只是提供一种思路。这篇文章也是这个系列中的第三篇文章。前两篇文章《基于gorm.io/sharding分表中间…...

【CSS】变量的声明与使用

原生变量root 伪类 原生变量 CSS中我们可以统一设置变量方便页面维护。变量声明的时候,自定义样式变量名之前加上两根连词线 " – " 即可,使用 var() 来引用。声明的变量是有作用域的 ( 比如是在html中声明的变量,那么该变量在html…...

【数学分析笔记】第3章第4节闭区间上的连续函数(1)

3. 函数极限与连续函数 3.4 闭区间上的连续函数 3.4.1 有界性定理 【定理3.4.1】 f ( x ) f(x) f(x)在闭区间 [ a , b ] [a,b] [a,b]上连续,则 f ( x ) f(x) f(x)在闭区间 [ a , b ] [a,b] [a,b]上有界。 【证】用反证法,假设 f ( x ) f(x) f(x)在 [ …...

Mybatis中sql数组为空判断

一、Mybatis xml中的sql通过if语句判定是否为空 <if test"arrays ! null"> </if>上述示例只能判断arrays数组不为null&#xff0c;那如果是个空数组呢 二、Mybatis xml中的sql通过if语句判定数组非空数组 <if test"arrays ! null and arrays.l…...

12.第二阶段x86游戏实战2-CE找基地址

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…...

笔记整理—内核!启动!—linux应用编程、网络编程部分(3)文件共享与标准IO

文件共享是指同一个文件被多个独立的读写进行操作。同一个文件为同一个inode&#xff0c;同一个pathname也就是同一个静态文件。同时进行操作&#xff0c;打开一个文件未关闭又被另一个操作打开。文件共享的方式可以实现高效的大文件读写。 文件共享的三种方式&#xff1a;①同…...

plt常用函数介绍一

目录 前言plt.figure()plt.subplot()plt.subplots()plt.xticks()plt.xlim() 前言 Matplotlib是Python中的一个库&#xff0c;它是数字的-NumPy库的数学扩展。 Pyplot是Matplotlib模块的基于状态的接口。在Pyplot中可以使用各种图&#xff0c;例如线图&#xff0c;轮廓图&#…...

基于ExtendSim的 电子制造 仿真模型

说明&#xff1a; 此模型表示电路板制造设施。该过程有4个步骤&#xff1a; *焊料制备 *组件放置 *烤箱 *检查 详情&#xff1a; *烤箱的容量为10张卡&#xff0c;但如果烤箱循环开始时仅能处理5张卡&#xff0c;则最多只能处理5张。 *如果检查员发现问题&#xff0c;他们将修理…...

BGP 路由反射器

转载&#xff1a;BGP 路由反射器 / 实验介绍: / 原理概述 缺省情况下&#xff0c;路由器从它的一个 IBGP 对等体那里接收到的路由条目不会被该路由器再传递给其他IBGP对等体&#xff0c;这个原则称为BGP水平分割 原则&#xff0c;该原则的根本作用是防止 AS 内部的 BGP 路由…...

CSRF高级防御绕过

1&#xff09;回顾low级别做过csrf页面的密码重置&#xff0c;重复之前的操作&#xff0c;我们发现级别调整中级之后&#xff0c;报错如下 2&#xff09;检查源码 进入dvwa源码&#xff0c;查找到checktoken&#xff1a; 3&#xff09;在dvwa-csrf页面上&#xff0c;抓包 http…...

MySQL安装文档-Windows

文章目录 MySQL安装1. 安装2. 配置 MySQL安装 1. 安装 1). 双击官方下来的安装包文件 2). 根据安装提示进行安装 安装MySQL的相关组件&#xff0c;这个过程可能需要耗时几分钟&#xff0c;耐心等待。 输入MySQL中root用户的密码,一定记得记住该密码 2. 配置 安装好MySQL之后…...

html TAB、table生成

1. 代码 <!DOCTYPE html> <head> <meta charset"UTF-8"> <title>Dynamic Tabs with Table Data</title> <style> /* 简单的样式 */ .tab-content { display: none; border: 10px solid #ccc; padding: 30px; mar…...

2024!再见前端!

各位朋友大家晚上好&#xff0c;夜深了&#xff0c;睡不着&#xff0c;想想还是写一篇文章和大家说再见吧&#xff01; 自2014年入行前端以来&#xff0c;满打满算差不多整整十年了&#xff0c;这十年可以说是见证了中国整个互联网的起飞到全盛时期。这期间经历了电商、金融、…...

【源码+文档+调试讲解】人事管理系统设计与实现Python

摘 要 人事管理系统的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff…...

Inconsolata字体深度解析:从代码美学到专业排版的完整方案

Inconsolata字体深度解析&#xff1a;从代码美学到专业排版的完整方案 【免费下载链接】Inconsolata Development repo of Inconsolata Fonts by Raph Levien 项目地址: https://gitcode.com/gh_mirrors/in/Inconsolata 在编程世界中&#xff0c;字体的选择远不止是审美…...

AI图像增强:让模糊照片重获新生的实用工具

AI图像增强&#xff1a;让模糊照片重获新生的实用工具 【免费下载链接】Real-ESRGAN-GUI Lovely Real-ESRGAN / Real-CUGAN GUI Wrapper 项目地址: https://gitcode.com/gh_mirrors/re/Real-ESRGAN-GUI 在数字时代&#xff0c;我们每个人的手机相册里都藏着珍贵的回忆—…...

魔兽地图跨版本转换与优化全指南:从兼容性处理到地图性能提升

魔兽地图跨版本转换与优化全指南&#xff1a;从兼容性处理到地图性能提升 【免费下载链接】w3x2lni 魔兽地图格式转换工具 项目地址: https://gitcode.com/gh_mirrors/w3/w3x2lni 在魔兽争霸III的地图开发领域&#xff0c;版本兼容性始终是开发者面临的核心挑战。不同游…...

我的实用设计模式之 关于Policy-based design在Windows Mobile网络连接管理的应用

Raw Data&#xff08;原数据&#xff09;使用不要的分析器&#xff08;分析器使用不同的算法&#xff09;分析出关心的Event&#xff08;事件&#xff0c;对象&#xff0c;告警等等&#xff09;。同时作为behavior模式之一&#xff0c;stragety模式也可以使用在 定义多个behavi…...

Qwen3-8B镜像站新手教程:如何选择模型并进行首次提问

Qwen3-8B镜像站新手教程&#xff1a;如何选择模型并进行首次提问 1. 认识Qwen3-8B&#xff1a;你的智能AI助手 Qwen3-8B是Qwen系列最新一代大型语言模型&#xff0c;拥有80亿参数&#xff0c;在推理能力、指令执行和多语言支持方面表现出色。这个模型特别适合个人开发者和小型…...

千问3.5-2B实战案例:直播截图实时分析→商品链接提取→竞品价格对比→话术生成

千问3.5-2B实战案例&#xff1a;直播截图实时分析→商品链接提取→竞品价格对比→话术生成 1. 项目背景与价值 在电商直播场景中&#xff0c;运营团队面临三个核心痛点&#xff1a; 直播过程中无法实时监测竞品价格动态人工记录商品信息效率低下且容易出错话术调整滞后于市场…...

【仅限头部金融科技团队内部流通】FastAPI 2.0 AI流式响应安全加固方案:防内存溢出、防连接耗尽、防Token泄露(含OWASP ASVS v4.0合规对照表)

第一章&#xff1a;FastAPI 2.0 AI流式响应安全加固方案全景概览FastAPI 2.0 引入了对 Server-Sent Events&#xff08;SSE&#xff09;与异步生成器的原生增强支持&#xff0c;使大语言模型&#xff08;LLM&#xff09;的流式响应&#xff08;如 token-by-token 输出&#xff…...

何时DCDC预降压+LDO二次线性稳压?

LDO 核心选型分界结论及优化要点核心选型分界结论以LDO输入输出压差ΔV为核心判断指标&#xff0c;结合输出功率、场景约束&#xff0c;通用选型规则如下&#xff1a;通用强制分界点&#xff1a;当ΔV≥2V&#xff0c;且输出功率≥100mW&#xff08;对应你之前的5V转3V70mA工况…...

SiameseUIE中文-base效果对比:在CLUE-NER和COTE-ABSA双基准测试

SiameseUIE中文-base效果对比&#xff1a;在CLUE-NER和COTE-ABSA双基准测试 想找一个开箱即用、效果又好的中文信息抽取工具&#xff1f;今天我们来聊聊阿里巴巴达摩院出品的SiameseUIE中文-base模型。这可不是一个普通的模型&#xff0c;它是一个“通用信息抽取”模型&#x…...

Java全栈工程师面试实录:从基础到实战的深度技术探讨

Java全栈工程师面试实录&#xff1a;从基础到实战的深度技术探讨 一、面试开场 面试官&#xff08;李工&#xff09;&#xff1a;你好&#xff0c;欢迎来到我们公司。我是李工&#xff0c;负责技术面试。今天我们会围绕你的技术栈进行一些深入交流。 应聘者&#xff08;张明&am…...