从GO内存模型与调用协议理解defer closure的坑
资料参考:
- 官网defer介绍: https://blog.golang.org/defer-panic-and-recover
- 深入解析go:
问题点
- 非命名返回值
package main
import "fmt"
func Test() (int) {
ret := 123
defer func() {
fmt.Println("first defer:",ret)
}()
defer func() {
ret++
fmt.Println("Inner:", ret)
}()
return ret
}
func main() {
fmt.Println(Test())
}
打印结果是123
- 命名返回值
package main
import "fmt"
func Test() (ret int) {
ret = 123
defer func() {
fmt.Println("first defer:",ret)
}()
defer func() {
ret++
fmt.Println("Inner:", ret)
}()
return ret
}
func main() {
fmt.Println(Test())
}
打印结果是124
前者123, 后者124? 怎么理解!
关键点
Go的return语句不是原子指令! 底层被分解为:
1. 返回值=xxx
2. 调用defer函数
3. 空的return
其实这种理解也是错的!
根据Go的内存模型及调用协议:
- GO在调用栈(Stack)的方法帧(frame)里, 在参数(arguments)之上保留返回值(returnValue)的位置.
方法帧(frame):
返回值0
返回值1
...
实参0
实参1
...
- return语句设置返回值. 如果是命名返回值, 则可在defer closure中引用.
- 执行defer函数栈.
从这个层面理解, return语句也是原子指令.
通俗说
- 根据Go的内存模型与调用协议知道, 函数帧会保留前N个位置用于保存返回值. 如果返回值是命名的, 则这几个位置可以直接访问.
- return语句将值设置到返回值的保留位置. 原则上说return语句也是原子指令.
- defer栈return语句或函数结束后调用. 如果操作了返回值(命名返回值), 其值是可见的!
需要明确的是, 非命名返回值一般不受影响.
但也可以看出, 命名返回值某种程度节省了赋值指令.
从GO内存模型与调用协议理解defer closure的坑的更多相关文章
- 对Java内存模型即JMM的理解
类似物理上的计算机系统,Java虚拟机规范中也定义了一种Java内存模型,即Java Memory Model(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能 ...
- Java内存模型解惑--观深入理解Java内存模型系列文章有感(二)
1.volatile关键字修饰的域的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用 ...
- Java内存模型原理,你真的理解吗?
[51CTO.com原创稿件]这篇文章主要介绍模型产生的问题背景,解决的问题,处理思路,相关实现规则,环环相扣,希望读者看完这篇文章后能对 Java 内存模型体系产生一个相对清晰的理解,知其然知其所以 ...
- 《深入理解Java虚拟机》-----第12章 Java内存模型与线程
概述 多任务处理在现代计算机操作系统中几乎已是一项必备的功能了.在许多情况下,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与它的存储和通信子系统速 ...
- 深入理解Java虚拟机内存模型
前言 本文中部分内容引用至<深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)>第12章,如果有兴趣可自行深入阅读,文末放有书籍PDF版本连接. 一.物理机中的并发 物理机遇到的并 ...
- 全面理解Java内存模型(JMM)及volatile关键字(转载)
关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...
- 全面理解Java内存模型(JMM)及volatile关键字(转)
原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...
- 如何从编程的本质理解JVM内存模型
如何从编程的本质理解JVM内存模型 一般聊JVM内存模型都是把图截出来,然后对着图,解释上面堆.栈之类的概念.这篇将分享下,如何从编程的本质上理解,JVM内存模型是什么样子,为什么是这个样子,不再死记 ...
- Java的内存模型
"让计算机并发执行若干个运算任务"与"更充分地利用计算机处理器的效能"之间的因果关系,看起来顺理成章,实际上它们之间的关系并没有想象中的那么简单,其中一个重要的 ...
随机推荐
- postman参数为Json数据结构
本文主要postman字段为Json结构时的操作说明 本文以订单发货为例,根据接口文档去设计 用户下单接口字段如图: 有两种方式可以将字段Json数据传递: 下图为接口字段规则: 接口为post请求方 ...
- JavaWeb(三)servlet
Servlet * 什么是Servlet 是运行在web服务器端的Java应用程序,它使用JAVA语言编写,具有Java语言的优点.与Java程序的区别:Servlet对象主要封装了对Http请求的处 ...
- storm学习笔记(一)
1.storm介绍 storm是一种用于事件流处理的分布式计算框架,它是有BackType公司开发的一个项目,于2014年9月加入了Apahche孵化器计划并成为其旗下的顶级项目之一. ...
- linux 系统状态分析
查看操作系统类型---返回结果Linux 适合与字符比较 cat /proc/sys/kernel/ostype cat /proc/version shell : www.jb51.net/arti ...
- python之路第二天 随便记记 今天主要很郁闷
为何要有操作系统 为了让程序员更轻松的完成命令电脑工作而存在的,控制硬件,服务于软件. 操作系统的位置 操作系统位于软件和硬件之间.操作系统由内核(运行于内核态,控制硬件)和系统调用(运行于用户态,为 ...
- Java的static关键字
本文参考:Java的static关键字 通过static关键字可以满足两方面的需要.一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象.另一种情形是,希 ...
- log4j源码解析
前言:本文将在slf4j的基础上解释log4j的应用,阅读本文前可先行阅读SLF4J源码解析-LoggerFactory(二) 前言概要 在前言中提到的slf4j的基础,其主要是通过logback的a ...
- app端性能测试笔记
IOS不清楚,我就说说android平台吧 1.按不同维度 APP级性能.代码级性能 app这一级 GT啊 emmage都可以检测 2.代码级性能的话 有可以分几块 函数性能UI ...
- fixed定位兼容性
不过从ios5.1以来,fixed定位就已经支持了,但很遗憾,ios现在对它还只是半支持. 但是在某些情况下,会出现一些比较奇葩的问题,比如fixed元素中存在输入框子元素,这个时候就会跪了. 可以看 ...
- 【小白成长撸】--顺序栈(C语言版)
// 顺序栈.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h"//test1.0--栈表仅限Int类型 #include <stdio. ...