广告
返回顶部
首页 > 资讯 > 精选 >Go语言中内存管理逃逸的方法是什么
  • 537
分享到

Go语言中内存管理逃逸的方法是什么

2023-07-05 12:07:05 537人浏览 薄情痞子
摘要

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

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

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:\SourceCode\GoExpert\src>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:\SourceCode\GoExpert\src>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.\main.go:4: Slice make([]int, 1000, 1000) does not escape

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

D:\SourceCode\GoExpert\src>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:\SourceCode\GoExpert\src>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 < 10; i++ {        fmt.Printf("Fibonacci: %d\n", f())    }}

上述代码通过Fibonacci()获取一个闭包,每次执行闭包就会打印一个Fibonacci数值。输出如下所示:

D:\SourceCode\GoExpert\src>src.exe
Fibonacci: 1
Fibonacci: 1
Fibonacci: 2
Fibonacci: 3
Fibonacci: 5
Fibonacci: 8
Fibonacci: 13
Fibonacci: 21
Fibonacci: 34
Fibonacci: 55

Fibonacci()函数中原本属于局部变量的a和b由于闭包的引用,不得不将二者放到堆上,以致产生逃逸:

D:\SourceCode\GoExpert\src>go build -gcflags=-m
# _/D_/SourceCode/GoExpert/src
.\main.go:7: can inline Fibonacci.func1
.\main.go:7: func literal escapes to heap
.\main.go:7: func literal escapes to heap
.\main.go:8: &a escapes to heap
.\main.go:6: moved to heap: a
.\main.go:8: &b escapes to heap
.\main.go:6: moved to heap: b
.\main.go:17: f() escapes to heap
.\main.go:17: main ... argument does not escape

4.逃逸总结

栈上分配内存比在堆中分配内存有更高的效率

栈上分配的内存不需要GC处理

堆上分配的内存使用完毕会交给GC处理

逃逸分析目的是决定内分配地址是栈还是堆

逃逸分析在编译阶段完成

5. 注意事项

思考一下这个问题:函数传递指针真的比传值效率高吗?

我们知道传递指针可以减少底层值的拷贝,可以提高效率,但是如果拷贝的数据量小,由于指针传递会产生逃逸,可能会使用堆,也可能会增加GC的负担,所以传递指针不一定是高效的。

“Go语言中内存管理逃逸的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Go语言中内存管理逃逸的方法是什么

本文链接: https://www.lsjlt.com/news/351663.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Go语言中内存管理逃逸的方法是什么
    本篇内容介绍了“Go语言中内存管理逃逸的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 前言所谓的逃逸分析(Escape an...
    99+
    2023-07-05
  • Go语言中内存管理逃逸分析详解
    目录1. 前言2. 逃逸策略3. 逃逸场景3.1 指针逃逸3.2 栈空间不足逃逸3.3 动态类型逃逸3.4 闭包引用对象逃逸4.逃逸总结5. 注意事项1. 前言 所谓的逃逸分析(Es...
    99+
    2023-03-15
    Go 内存管理逃逸分析 Go 内存管理逃逸 Go 内存管理
  • Go语言中的逃逸分析究竟是什么?
    目录1、逃逸分析介绍2、Go中内存分配在哪里?3、Go与C++内存分配的区别4、逃逸分析骚操作5、逃逸分析引申示例说明 1、逃逸分析介绍 学计算机的同学都知道,在编译原理中,分析指针...
    99+
    2022-11-12
  • golang内存逃逸的原因及解决方法是什么
    在Go语言中,内存逃逸指的是在函数内部分配的变量在函数执行完后仍然被其他部分引用,导致变量逃逸到堆上分配内存,而不是在栈上分配内存。...
    99+
    2023-10-23
    golang
  • go语言内存管理的方法有哪些
    Go语言内存管理的方法有以下几种:1. 垃圾回收(Garbage Collection):Go语言使用自动垃圾回收机制来管理内存。垃...
    99+
    2023-09-27
    go语言
  • C语言动态内存管理的方法是什么
    本文小编为大家详细介绍“C语言动态内存管理的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言动态内存管理的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.为什么需要动态内存分配关于这个...
    99+
    2023-06-29
  • go语言内存申请和释放的方法是什么
    在Go语言中,内存的申请和释放是由Go的垃圾回收器自动管理的,开发者不需要手动申请和释放内存。Go语言使用了自动垃圾回收(Garba...
    99+
    2023-10-20
    go语言
  • C语言与C++中内存管理的方法
    这篇文章主要介绍了C语言与C++中内存管理的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言与C++中内存管理的方法文章都会有所收获,下面我们一起来看看吧。内存分布主要段及其分布每个程序运行起来以后,它...
    99+
    2023-06-30
  • C语言/C++内存管理是什么
    本篇内容介绍了“C语言/C++内存管理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、内存在计算机中,每个应用程序之间的内存是相互独...
    99+
    2023-06-16
  • C语言可变参数使用与内存管理的方法是什么
    这篇“C语言可变参数使用与内存管理的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言可变参数使用与内存管理的方...
    99+
    2023-07-04
  • 如何解决Go语言中的内存管理问题?
    如何解决Go语言中的内存管理问题?在Go语言中,内存管理是一个重要的话题。由于Go语言自带的垃圾回收器(Garbage Collector)的存在,开发者不需要手动管理内存分配和释放,但这并不意味着我们可以完全忽视内存管理的问题。不合理的内...
    99+
    2023-10-22
    解决方案 Go语言 内存管理
  • go语言删除文件内容的方法是什么
    go语言删除文件内容的方法是:1、删除文件并重新创建一个同名的空文件,使用os.Create()函数创建一个同名的空文件;2、使用os.Create()函数接受一个文件路径作为参数,并返回一个文件对象。Go语言是一种快速、简洁、并发性高的编...
    99+
    2023-07-10
  • C语言的动态内存管理是什么意思
    这篇文章将为大家详细讲解有关C语言的动态内存管理是什么意思,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、动态内存分配(1)用malloc类的函数分配内存;(2)用这些内存支持应用程序;(3)用free...
    99+
    2023-06-29
  • Go语言中最有效的存储数组方法是什么?
    在Go语言中,数组是一种常见的数据结构,它可以存储一组相同类型的数据。但是在存储大量数据时,如何选择最有效的数组存储方法呢?本文将为您介绍Go语言中最有效的存储数组方法。 使用数组 在Go语言中,最基本的数组存储方法就是使用数组。数组...
    99+
    2023-09-23
    关键字 存储 数组
  • GO语言中的缓存管理:容器框架的实现原理是什么?
    随着网络技术的不断发展,数据量的不断增加,对数据的快速响应成为了当今互联网应用的重要问题。在这个背景下,缓存技术作为一种优化手段越来越受到开发者的关注。而GO语言因为其高效性、简洁性和可扩展性,成为了越来越多开发者选择的语言。那么,在GO...
    99+
    2023-07-24
    容器 框架 缓存
  • c语言内存泄漏的解决方法是什么
    在C语言中,内存泄漏是指在动态内存分配后,没有释放该内存导致内存空间无法被再次使用的情况。解决内存泄漏的方法可以包括以下几个方面:1...
    99+
    2023-09-27
    c语言
  • 理解Go语言内存优化的核心原则与方法
    Go语言内存优化的核心原则是尽量减少内存的分配和释放操作,以减少垃圾回收的压力和提高程序性能。以下是一些常见的方法和技巧:1. 使用...
    99+
    2023-10-08
    Golang
  • C语言动态内存管理的原理及实现方法
    目录1. 为什么存在动态内存分配2. 动态内存函数的介绍2.1 malloc和free2.2 calloc2.3 realloc3. 常见的动态内存错误3.1 对NULL指针的解引用...
    99+
    2023-05-16
    C语言动态内存管理 C语言内存管理
  • golang手动管理内存的方法是什么
    在Go语言中,手动管理内存的方法包括使用unsafe包、手动分配和释放内存以及手动管理指针。 使用unsafe包:unsafe包...
    99+
    2023-10-23
    golang
  • golang内存分配管理的方法是什么
    Go语言中的内存分配管理主要有两个方法: 垃圾回收:Go语言使用了自动垃圾回收(Garbage Collection)来管理内存...
    99+
    2023-10-26
    golang
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作