未加星标

Go:在defer指定的函数中修改返回值会出现的几种情况

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二04 | 时间 2018 | 作者 红领巾 ] 0人收藏点击收藏
说明

Go语言的手册中 Defer statements 明确说了可以在defer中修改 命名的返回的变量(named result parameters ) :

For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned. If the deferred function has any return values, they are discarded when the function completes. (See also the section on handling panics.)

但是对修改非命名的返回变量,却没有明确的说法。

试验 // Create: 2018/12/07 10:03:00 Change: 2018/12/07 10:03:00 // FileName: a.go // Copyright (C) 2018 lijiaocn <lijiaocn@foxmail.com> // // Distributed under terms of the GPL license. package main //change in defer,result is 2 func det1() int { result := 2 defer func() { println("det1") result = 1 }() return result } //change pointer in defer, result is 2 func det2() int { result := 2 defer func(result *int) { println("det2") *result = 1 }(&result) return result } //use name result and change in defer, result is 1 func det3() (result int) { result = 2 defer func() { println("det3") result = 1 }() return result } //return is pointer,result is 1 func det4() *int { result := 2 defer func() { println("det4") result = 1 }() return &result } func main() { a := det1() b := det2() c := det3() d := det4() println(a) println(b) println(c) println(*d) }

输出结果如下:

det1 det2 det3 det4 2 2 1 1

其中最让人不能理解的是 det2() ,defer中修改的是指针指向的内容,但是返回的结果没有变化:

//change pointer in defer, result is 2 func det2() int { result := 2 defer func(result *int) { println("det2") *result = 1 }(&result) return result }

出现这种情况,只有一个解释,在defer指定的函数执行之前,函数的返回值就已经确定了,defer中的更改是不生效的。

但是 det4() 中的修改又是有效的:

//return is pointer,result is 1 func det4() *int { result := 2 defer func() { println("det4") result = 1 }() return &result }

结合 det2() 的结果推断,return的返回值不仅是在defer指定函数执行之前确定的,而且是拷贝了一份。

det3() 又怎样解释呢?return的返回值是命名变量的时候,不做拷贝?

//use name result and change in defer, result is 1 func det3() (result int) { result = 2 defer func() { println("det3") result = 1 }() return result } 分析一下汇编代码

用下面的命令编译:

GOARCH=amd64 GOOS=linux go build

然后将得到的二进制程序反汇编:

go tool objdump -S defer >defer.asm //用go tool反汇编 objdump -d -t defer >defer.asm //linux上用objdump反汇编

有空继续分析..(2018-12-07 14:04:14)

参考 X86 Assembly/GAS Syntax Intel 64 and IA-32 Architectures Software Developer’s Manual:Volume 2 (2A, 2B, 2C & 2D): Instruction Set Reference, A-Z CPU的相关知识 Using as

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

分页:12
转载请注明
本文标题:Go:在defer指定的函数中修改返回值会出现的几种情况
本站链接:https://www.codesec.net/view/620856.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(11)