内容简介:A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a通过使用为什么输出的是"Hello": 在 defer 中, fmt.Print 被推迟到函数返回后执行,可是 m.print() 的值在当时就已经被求出,因此, m.print(
什么是defer
A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement , reached the end of its function body , or because the corresponding goroutine is panicking .
通过使用 defer
修饰一个函数,使其在外部函数返回后才被执行,一种是因为周围的函数执行了一个 return
语句,到达了它的函数体的末尾,另一种是因为相应的goroutine是 panicking
先看example1
package main import "fmt" func main() { data1 := example1() fmt.Printf("output1:%v\n", data1) data2 := example2() fmt.Printf("output2:%v\n", data2) data3 := example3() fmt.Printf("output3:%v\n", data3) } func example1() (result int) { defer func() { result++ }() return 0 } func example2() (r int) { t := 1 defer func() { t = t + 1 }() return t } func example3() (r int) { defer func(r int) { r = r + 1 }(r) return 1 } //output1:1 //output2:1 //output3:1
go 函数返回值的栈空间与执行顺序
- golang 的返回值是通过栈空间,不是通过寄存器,这点最重要。调用函数前,首先分配的是返回值空间,然后是入参地址,再是其他临时变量地址。
-
return 是非原子的,return 操作的确是分三步:
将返回值拷贝到栈空间第一块区域,即:返回值 = x
执行defer 操作, 即: 调用defer函数
RET 跳转, 即:返回
这个操作的确是可以对应到汇编代码的。
example4
package main import "fmt" type message struct { content string } func (p *message) set(c string) { p.content = c } func (p *message) print() string { return p.content } func main() { m := &message{content: "Hello"} defer fmt.Println(m.print()) //m.print() == "Hello", 将值拷贝进去 m.set("World") } //输出:Hello
为什么输出的是"Hello": 在 defer 中, fmt.Print 被推迟到函数返回后执行,可是 m.print() 的值在当时就已经被求出,因此, m.print() 会返回 "Hello" ,这个值会保存一直到外围函数返回。
example4 改进
package main import "fmt" type message struct { content string } func (p *message) set(c string) { p.content = c } func (p *message) print() string { return p.content } func main() { m := &message{content: "Hello"} defer func() { fmt.Println(m.print()) }() m.set("World") } //输出:World
对 m 地址的引用
example 5
package main import ( "errors" "fmt" "io" ) type reader struct{} func (r reader) Close() error { return errors.New("Close Error") } func release(r io.Closer) (err error) { defer func() { if err := r.Close(); err != nil{ fmt.Println("my errors") } }() return } func main() { r := reader{} err := release(r) fmt.Println(err) } //输出:my errors //输出:<nil>
example 5改进
package main import ( "errors" "fmt" "io" ) type reader struct{} func (r reader) Close() error { return errors.New("Close Error") } func release(r io.Closer) (err error) { defer func() { if err = r.Close(); err != nil{ fmt.Println("my errors") } }() return } func main() { r := reader{} err := release(r) fmt.Println(err) } //输出: my errors //输出:Close Error
因为变量的作用域不同导致的块级屏问题。将 err := r.Close() 改成 err = r.Close 即可。
example 6 忽略了错误
func do() error { f, err := os.Open("book.txt") if err != nil { return err } defer f.Close() // ..code... return nil }
example 6 改进
func do() (err error) { f, err := os.Open("book.txt") if err != nil { return err } defer func() { if ferr := f.Close(); ferr != nil { err = ferr } }() // ..code... return nil }
以上所述就是小编给大家介绍的《Go defer分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
- EOS源码分析(3)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to the Design and Analysis of Algorithms
Anany Levitin / Addison Wesley / 2006-2-24 / USD 122.00
Based on a Based on a new classification of algorithm design techniques and a clear delineation of analysis methods, "Introduction to the Design and Analysis of Algorithms" presents the subject in a c......一起来看看 《Introduction to the Design and Analysis of Algorithms》 这本书的介绍吧!
UNIX 时间戳转换
UNIX 时间戳转换
RGB HSV 转换
RGB HSV 互转工具