当前位置:首页 > 文章列表 > Golang > Go教程 > 一文聊聊Golang中内存管理逃逸的方法

一文聊聊Golang中内存管理逃逸的方法

来源:亿速云 2023-03-15 17:11:59 0浏览 收藏

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《一文聊聊Golang中内存管理逃逸的方法》,就很适合你,本篇文章讲解的知识点主要包括go语言。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!

本篇内容介绍了“一文聊聊Golang中内存管理逃逸的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1. 前言

所谓的逃逸分析(Escape analysis)是指由编译器决定内存分配的位置吗不需要程序员指定。

函数中申请一个新的对象

  • 如果分配在栈中, 则函数执行结束后可自动将内存回收

  • 如果分配在堆中, 则函数执行借宿可交给GC(垃圾回收)处理

有了逃逸分析,返回函数局部变量将变得可能,除此之外,逃逸分析还跟闭包息息相关,了解哪些场景下对象会逃逸至关重要。

2. 逃逸策略

每当函数中申请新的对象,编译器会根据该对象是否被函数外部引用来决定是否逃逸:

  • 如果函数外部没有引用,则优先放到栈中;

  • 如果函数外部存在引用,则必定放到堆中;

注意,对于函数外部没有引用的对象,也有可能放到堆中,比如内存过大超过栈的存储能力。

3. 逃逸场景

3.1 指针逃逸

我们知道Go可以返回局部变量指针,这其实是一个典型的变量逃逸案例,示例代码如下:

package main
 
type Student struct {
    Name string
    Age  int
}
 
func StudentRegister(name string, age int) *Student {
    s := new(Student) //局部变量s逃逸到堆
 
    s.Name = name
    s.Age = age
 
    return s
}
 
func main() {
    StudentRegister("Jim", 18)
}

函数StudentRegister()内部s为局部变量,其值通过函数返回值返回,s本身为一指针,其指向的内存地址不会是栈而是堆,这就是典型的逃逸案例。

通过编译参数-gcflag=-m可以查看编译过程中的逃逸分析:

D:SourceCodeGoExpertsrc>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.main.go:8: can inline StudentRegister
.main.go:17: can inline main
.main.go:18: inlining call to StudentRegister
.main.go:8: leaking param: name
.main.go:9: new(Student) escapes to heap
.main.go:18: main new(Student) does not escape

可见在StudentRegister()函数中,也即代码第9行显示”escapes to heap”,代表该行内存分配发生了逃逸现象。

3.2 栈空间不足逃逸

看下面的代码,是否会产生逃逸呢?

package main
 
func Slice() {
    s := make([]int, 1000, 1000)
 
    for index, _ := range s {
        s[index] = index
    }
}
 
func main() {
    Slice()
}

上面代码Slice()函数中分配了一个1000个长度的切片,是否逃逸取决于栈空间是否足够大。

直接查看编译提示,如下:

D:SourceCodeGoExpertsrc>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.main.go:4: Slice make([]int, 1000, 1000) does not escape

我们发现此处并没有发生逃逸。那么把切片长度扩大10倍即10000会如何呢?

D:SourceCodeGoExpertsrc>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.main.go:4: make([]int, 10000, 10000) escapes to heap

我们发现当切片长度扩大到10000时就会逃逸。

实际上当栈空间不足以存放当前对象时或无法判断当前切片长度时会将对象分配到堆中。

3.3 动态类型逃逸

很多函数参数为interface类型,比如fmt.Println(a …interface{}),编译期间很难确定其参数的具体类型,也会产生逃逸。

如下代码所示:

package main
 
import "fmt"
 
func main() {
    s := "Escape"
    fmt.Println(s)
}

上述代码s变量只是一个string类型变量,调用fmt.Println()时会产生逃逸:

D:SourceCodeGoExpertsrc>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.main.go:7: s escapes to heap
.main.go:7: main ... argument does not escape

3.4 闭包引用对象逃逸

某著名的开源框架实现了某个返回Fibonacci数列的函数:

func Fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

该函数返回一个闭包,闭包引用了函数的局部变量a和b,使用时通过该函数获取该闭包,然后每次执行闭包都会依次输出Fibonacci数列。
完整的示例程序如下所示:

package main
 
import "fmt"
 
func Fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}
 
func main() {
    f := Fibonacci()
 
    for i := 0; i
版本声明
本文转载于:亿速云 如有侵犯,请联系study_golang@163.com删除
Go语言+MongoDB如何实现在另一个结构中嵌入一个结构Go语言+MongoDB如何实现在另一个结构中嵌入一个结构
上一篇
Go语言+MongoDB如何实现在另一个结构中嵌入一个结构
浅析Golang怎么实现锁
下一篇
浅析Golang怎么实现锁
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    3164次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    3376次使用
  • 可赞AI:AI驱动办公可视化智能工具,一键高效生成文档图表脑图
    可赞AI
    可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
    3405次使用
  • 星月写作:AI网文创作神器,助力爆款小说速成
    星月写作
    星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
    4509次使用
  • MagicLight.ai:叙事驱动AI动画视频创作平台 | 高效生成专业级故事动画
    MagicLight
    MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
    3785次使用
查看更多
相关文章
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码