Go 内存逃逸分享

内存逃逸

是指编译器决定内存分配的位置,不需要程序员指定。
在函数中申请一个新的对象:

  1. 如果分配在栈中,则函数执行结束后可自动将内存回收;
  2. 如果分配在堆中,则函数结束后需要交给GC进行处理。

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

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

逃逸场景
1)指针逃逸
函数返回局部变量指针,函数内部定义的指针变量原本是在栈空间中开辟,但是函数将此局部变量返回出去了,那么指向该变量的内存地址是堆。

2)栈空间不足逃逸
当栈空间不足以存放当前对象或无法判断当前切片长度是会将对象分配到堆中。

3)动态类型逃逸
由于很多函数的类型是interface{} ,在编译期间很难确定其参数具体类型,也会产生逃逸

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

变量s是一个string类型的变量,在调用fmt.Println()时发生了逃逸。

4)闭包引用对象逃逸
举一个斐波那契数列的例子

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

func main(){
	f := Fib()
	for i:=0; i<10;i++{
		fmt.Printf("Fib: %d\n", f())
	}
}

闭包引用了函数的局部变量a、b,通过Fib函数获取闭包,每次执行闭包都会输出Fib数列。
而由于闭包中引用了变量a、b,所以导致两个变量的内存逃逸到了堆上。

小结

  1. 栈上分配内存比在堆中分配内存有更高的效率;
  2. 栈上分配的内存不需要GC;
  3. 堆上分配的内存使用完成之后交给GC处理;
  4. 逃逸分析的目的是决定分配地址是栈还是堆;
  5. 逃逸分析是在编译阶段完成。

question:函数传递指针真的比传值效率高吗

answer:传递指针可以减少底层值的复制,可以提高效率,但是如果复制的数据量小,由于指针传递会产生逃逸,则很有可能使用堆,从而加重GC的负担,所以传递指针不一定是高效的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Go语言中,内存逃逸指的是当一个对象的指针被多个方法或线程引用时,这个指针会逃逸到堆上。内存逃逸的位置由编译器决定,而不像C或C++可以使用malloc或new在堆上分配内存。根据内存分配的基本原则,当函数外部对指针没有引用时,优先分配在栈上;当函数外部对指针存在引用时,优先分配在堆上;当函数内部分配一个较大对象时,优先分配在堆上。\[1\] 在Go语言中,内存逃逸分析可以通过一些规则来判断。例如,当使用等号=赋值时,如果Data和Field都是引用类型的数据,则会导致Value逃逸。另外,一些特定的数据类型也会导致逃逸,比如\[\]interface{}、map\[string\]interface{}、map\[interface{}\]interface{}、map\[string\]\[\]string、map\[string\]*int、\[\]*int、func(*int)、func(\[\]string)、chan \[\]string等。具体的规则可以参考引用\[2\]中的示例。\[2\] 此外,栈空间不足也可能导致内存逃逸。当在函数中创建一个较大的切片或数组,并且栈空间不足以容纳它们时,这些切片或数组会逃逸到堆上。例如,在一个函数中创建一个长度为10000的切片,如果栈空间不足,这个切片就会逃逸到堆上。\[3\] 总结来说,内存逃逸是指当一个对象的指针被多个方法或线程引用时,这个指针会逃逸到堆上。在Go语言中,内存逃逸的位置由编译器决定,可以通过一些规则和栈空间的判断来进行分析。 #### 引用[.reference_title] - *1* [golang内存逃逸分析](https://blog.csdn.net/qq_42170897/article/details/127770234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [golang内存逃逸](https://blog.csdn.net/wanghao3616/article/details/107284523)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [golang——内存逃逸机制](https://blog.csdn.net/weixin_45627369/article/details/127163797)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hewesH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值