最全golang_逃逸分析_golang escapes to heap(1),2024年最新HTTPS面试常问全解析

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取


前言

所谓逃逸分析(Escape analysis)是指由编译器决定内存分配的位置,不需要程序员指定。 函数中申请一个新的对象

  1. 如果分配在栈中,则函数执行结束可自动将内存回收
  2. 如果分配在堆中,则函数执行结束可交给GC(垃圾回收)处理

有了逃逸分析,返回函数局部变量将变得可能,除此之外,逃逸分析还跟闭包息息相关。

一、逃逸策略

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

  1. 如果函数外部没有引用,则优先放到栈中;
  2. 如果函数外部存在引用,则必定放到堆中;

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

二、逃逸场景

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本身为一指针,其指向的内存地址不会是栈而是堆,这就是典型的逃逸案例。

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.动态类型逃逸

很多函数参数为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

4.闭包引用对象逃逸

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


![img](https://img-blog.csdnimg.cn/img_convert/90175537a2456c25cb344575720d0f82.png)
![img](https://img-blog.csdnimg.cn/img_convert/5934503f595990824871be5f5c2d124f.png)
![img](https://img-blog.csdnimg.cn/img_convert/edb3584cfbab403df114f12dc7a4259c.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**


**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值