Golang中逃逸现象, 变量“何时栈?何时堆?”

目录

什么是栈

什么是堆

栈 vs 堆(核心区别)

GO编译器的逃逸分析

什么是逃逸分析?

怎么看逃逸分析结果?

典型“会逃逸”的场景

闭包捕获局部变量

返回或保存带有“底层存储”的容器

经由接口/反射/fmt 等导致装箱或被长期保存

把指针/引用存入全局、堆对象或长生命周期结构

​​​​​​​参数“内容”被函数保留(编译器推不动)

GO中的“堆/栈”怎么落地

落地

是否上堆由逃逸分析决定

什么时候“应该”用谁?


什么是栈

是每个线程私有、按先进后出管理的调用临时区。

什么是堆

是进程共享、由内存分配器/GC统一管理的动态内存区。

栈 vs 堆(核心区别)

  • 归属:栈是“每个线程一个栈”;堆是“整个进程(多线程)共享一大片内存”

  • 用途:栈放调用过程相关的数据(返回地址、保存寄存器、局部变量等);堆放动态创建、可跨函数/长期存在的数据

  • 生命周期:栈随函数返回自动回收(栈帧弹出);堆由程序(free/delete)或垃圾回收器回收

  • 分配/释放成本:栈是简单的指针移动,极快;堆需要向分配器申请/释放,相对慢

  • 访问局部性:栈一般连续,缓存友好;堆可能碎片化

  • 常见错误:栈——递归太深/局部数组过大导致栈溢出;堆——内存泄漏/重用已释放内存/碎片

  • 大小:栈通常较小且固定/可增长(按语言/平台而定);堆通常大很多(由 OS/运行时管理)

GO编译器的逃逸分析

go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析(escape analysis)当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。 go语言声称这样可以释放程序员关于内存的使用限制,更多的让程序员关注于程序功能逻辑本身。

什么是逃逸分析?

编译器在编译期判断一个变量是否会在当前函数返回后仍被引用(“逃出”当前栈帧)。

  • 不逃逸 → 尽量放在上,分配/回收极快;

  • 逃逸 → 放到上,由运行时/GC 管理,带来分配与 GC 成本。

怎么看逃逸分析结果?

在你的包目录运行(推荐关掉内联更好读):

go build -gcflags='all=-m -l' ./...
# 或者对测试/基准:
go test  -run=^$ -bench=. -gcflags='all=-m -l' ./...

常见输出含义:

  • moved to heap: x / escapes to heap:变量 x 上堆了

  • does not escape:未逃逸(可栈上)

  • leaking param / leaking param content:把参数或其内容泄露到了可能长寿命的位置(导致逃逸)

典型“会逃逸”的场景

返回局部变量的地址/引用

func f1() *int {x := 10return &x // x 逃逸:必须活到函数返回之后
}

闭包捕获局部变量

func f2() func() {x := 0return func() { x++ } // x 被闭包捕获 → 逃逸
}

返回或保存带有“底层存储”的容器

func f3(n int) []int {s := make([]int, n)return s // s 的底层数组需在返回后仍然存活 → 逃逸
}

经由接口/反射/fmt 等导致装箱或被长期保存

func f4(b []byte) {_ = fmt.Sprintf("%x", b) // b 常见会逃逸(fmt 可变参、接口装箱)
}

​​​​​​​把指针/引用存入全局、堆对象或长生命周期结构

var g []*T
func f5(p *T) {g = append(g, p) // p 的“内容”被长期保存 → 逃逸
}

​​​​​​​参数“内容”被函数保留(编译器推不动)

func keepPtr(pp **int) { stash = *pp } // 比如存到包级变量
func caller() {x := 1p := &xkeepPtr(&p) // 报 "leaking param content: p"
}

GO中的“堆/栈”怎么落地

落地

  • 语法上没有显式“栈/堆”关键字;逃逸分析决定变量放栈还是堆

  • 一般规律:不逃逸的局部数据可在栈上;返回到函数外/被闭包捕获等会逃逸到堆

  • make(slice/map/channel)和 new 只是创建方式,是否上堆由逃逸分析决定,堆内存由 GC 回收

是否上堆由逃逸分析决定

type T struct { buf [1024]byte }func f() *T {t := T{}   // 语义上是局部变量;若返回其地址 => 逃逸到堆(由编译器决定)return &t
}func g() {t := T{}   // 不逃逸的话,可能在栈上分配,函数返回就回收_ = t
}

什么时候“应该”用谁?

  • 短生命周期、只在当前调用链内使用:栈(语言通常自动用栈)

  • 需要跨函数/跨协程/长期缓存:堆(动态分配)

  • 在拥有 GC 的语言(Go/Java/Python)中,写法更关注语义,由编译器/运行时决定最终放栈还是堆;只需要留意可能引发逃逸的用法和不必要的大对象分配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95661.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL入门指南:从安装到工作原理

什么是MySQL MySQL是一个开源的关系型数据库管理系统,由瑞典MySQL AB公司开发(目前属于Oracle公司),被广泛地应用在大中小型网站中 MySQL是一个小型的开源的关系型数据库管理系统,与其他大型数据库管理系统例如&…

dask.dataframe.shuffle.set_index中获取 divisions 的步骤分析

dask.dataframe.shuffle.set_index 中获取 divisions 的步骤分析 主要流程概述 在 set_index 函数中,当 divisionsNone 时,系统需要通过分析数据来动态计算分区边界。这个过程分为以下几个关键步骤: 1. 初始检查和准备 if divisions is None:…

ai生成ppt工具有哪些?10款主流AI生成PPT工具盘点

随着人工智能技术的飞速发展,AI生成PPT工具逐渐成为职场人士、学生和创作者提升效率的得力助手。这类工具通过智能算法,能够快速将文本、数据或创意转化为结构化、视觉化的演示文稿,大幅节省设计时间。1、AiPPT星级评分:★★★★★…

Qt多线程编程学习

Qt多线程编程学习 1. 项目概述 本项目展示了Qt中多线程编程的基本用法,通过继承QThread类创建自定义线程,并演示了线程的启动、执行和销毁过程。项目包含一个简单的用户界面,用户可以通过按钮控制线程的启动和结束。 1.1 项目结构 项目包含以…

加密货币武器化:恶意npm包利用以太坊智能合约实现隐蔽通信

ReversingLabs研究人员发现两个恶意npm包利用以太坊(Ethereum)智能合约隐藏并传播恶意软件。这两个名为colortoolsv2和mimelib2的软件包于2025年7月被识别,展现了开源安全攻防战中的新战术。恶意软件包伪装成实用工具攻击活动始于7月7日发布的…

Spring Boot 全局字段处理最佳实践

在日常开发中,我们总会遇到一些琐碎但又无处不在的字段处理需求:• 请求处理: 用户提交的表单,字符串前后带了多余的空格,需要手动 trim()。• 响应处理: 返回给前端的 BigDecimal 金额,因为精度问题导致JS处理出错&am…

三坐标测量机在汽车制造行业中的应用

在汽车制造业中,零部件精度决定着整车性能。从发动机活塞的微米级公差,到车身焊接的毫米级间隙,汽车制造“差之毫厘,谬以千里” ,任何细微偏差都可能引发连锁反应:发动机抖动、异响、油耗飙升,车…

机床夹具设计 +选型

机床夹具设计—第2组(钻床夹具)仿真组装视频_哔哩哔哩_bilibili 夹具-商品搜索-怡合达一站式采购平台 米思米FA标准品电子目录new 可能要吧这些定位块单独用yolo训练一边才能搞识别分析 3长条一短销定位,黄色的用来夹紧 一个面加一短轴一棱…

表格识别技术:通过计算机视觉和OCR,实现非结构化表格向结构化数据的转换,推动数字化转型。

在日常工作和生活中,我们无处不在与表格打交道。从财务报表、发票收据,到科研论文中的数据表、医疗报告,表格以其清晰、结构化的方式,承载着大量关键信息。然而,当这些表格以纸质或图片等非结构化形式存在时&#xff0…

Go基础(②Viper)

Viper 读取配置创建一个配置文件 config.yamlserver:port: 8080timeout: 30 # 超时时间(秒) database:host: "localhost"user: "root"password: "123456"name: "mydb"然后用 Viper 读取这个配置,代…

kafka Partition(分区)详解

一、什么是 PartitionPartition(分区) 是 Kafka Topic(主题) 的最小并行单位。一个 Topic 可以包含多个 Partition,每个 Partition 底层对应一个有序、不可变的消息队列,消息只会顺序追加。Partition 内部消…

中创中间件适配HGDB

文章目录环境文档用途详细信息环境 系统平台:Microsoft Windows (64-bit) 10 版本:5.6.5 文档用途 本文章主要介绍中创中间件简单适配HGDB。 详细信息 一、数据源配置 1.数据库准备 (1)安装HGDB并创建一个名为myhgdb的数据…

服务器内存和普通计算机内存在技术方面有什么区别?

服务器内存和普通计算机内存在技术上的区别,主要体现在为满足不同工作场景和要求而采用的设计和特性上。下面这个表格汇总了它们的主要技术差异,方便你快速了解: ​技术特性​​服务器内存​​普通计算机内存​​错误校验 (ECC)​​支持ECC(…

哪款AI生成PPT工具对职场新人最友好?操作门槛最低的是哪个?

一句话生成专业PPT,职场新人也能轻松做出高质量演示文稿现代职场节奏快,PPT制作已成为必备技能。然而,职场新人常面临两大挑战:缺乏设计经验,以及需要在有限时间内完成高质量演示。传统PPT制作耗时费力,需梳…

1.注解的力量:Spring Boot如何用注解重构IoC容器

文章目录1.1 IoC容器:Spring的智能管家1.2 注解驱动:给管家下指令1.2.1 SpringBootApplication:总管家的聘书1.2.2 组件注解:员工的身份标识1.2.3 Autowired:依赖注入的三种方式1.2.4 Bean注解:手动招聘特殊…

【算法】92.翻转链表Ⅱ--通俗讲解

一、题目是啥?一句话说清 给你一个链表和两个整数 left 和 right,反转从第 left 个节点到第 right 个节点的子链表,并返回反转后的链表。其他部分保持不变。 示例: 输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5](反转了从第2到第4个节点) 二、解题…

Nature子刊:新发现!深层脑网络中发现强迫症症状的神经生物标志物

强迫症(OCD)是一种令人困扰的精神疾病,患者常常被强迫思维和强迫行为所困扰。例如,有些人会反复洗手,无法控制自己的清洁冲动;还有些人会不断检查门窗是否关好,即便他们已经确认过无数次。这些行…

Onlyoffice集成与AI交互操作指引(Iframe版)

Onlyoffice集成与AI交互操作指引(Iframe版) 本文档系统介绍了软件系统集成OnlyOffice实现在线编辑与AI辅助功能的方案。主要内容包括:后端需提供文档配置信息并实现Callback接口以处理文档保存;前端通过Vue集成编辑器&#xff0c…

TypeScript 中 keyof、typeof 和 instanceof

在 TypeScript 开发中,keyof、typeof 和 instanceof 是核心的类型操作符和操作符,专门用于提升类型安全、代码可读性和维护性。1. keyof 操作符定义和用途:keyof 是一个类型操作符,用于获取对象类型的所有键(属性名&am…

分布式专题——1.1 Redis单机、主从、哨兵、集群部署

1 Redis 部署 下面演示在 Linux 环境下部署 Redis7。 1.1 单机部署 1.1.1 检查安装 gcc 环境Redis 是由 C 语言编写的,它的运行需要 C 环境,因此我们需要先安装 gcc; # 关闭防⽕墙 systemctl stop firewalld.service # 查看防火墙状态 firewa…