go语言之defer

栏目: Go · 发布时间: 5年前

/*1 适用于函数和方法,只能跟方法或者函数
*/
/*2 defer语句延迟执行直到函数return或者panic
return函数不是原子级,包括写入返回参数及
函数返回,defer语句在写入返回参数后函数返
回前执行
*/
/*3 defer语句反顺序执行(栈)一般用于成对
打开、关闭、连接、断开连接、加锁、释放锁
释放资源
*/
/*4 defer语句所在处变量入栈,只是函数结束再处理
    该语句,若值传递则后续值改变不影响defer语句,
    若地址传递则影响defer语句
    defer函数参数在defer语句执行时初始化
    defer函数调用时具体执行
4.1 defer记录函数的进入和退出,trace函数
*/
/*5 方法为一种数据类型,方法定义后,通过赋值给具有方法的
数据类型,则方法的类型与赋值类型一致,可以执行方法操作
*/
/*6 Each time a "defer" statement executes, the function value
and parameters to the call are evaluated as usualand saved anew
but the actual function is not invoked.
anew: 重新再
*/
/*7 defer函数调用函数返回值与函数输入参数按正常函数处理(复制新参数),
闭包函数变量更新defer函数中变量更新,但实际函数没有激活。
*/
/*8 函数返回的过程是这样子的:先给返回值赋值,然后调用defer表达式,
最后才是返回到调用函数中。利用闭包defer函数(指针)可修改返回值的值.
*/
/*9 defer表达式可能会在设置函数返回值之后,在返回到调用函数之前,
修改返回值,使最终的函数返回值与你想象的不一致
*/
/*10 defer+panic
无panic的函数按defer正常执行: defer定义,func return/panic执行
defer
panic 的函数仅执行panic之后语句不执行
*/
//
package main

import (
    "fmt"
    "log"
    "time"
)

//定义方法
type defMeth struct {
    err bool
    str string
}
//定义接口,接口为一种数据类型,提供操作
type in interface {
    ini()
    prinOut()
}

func (def *defMeth) ini() {
    def.err = true
    def.str = "hei"
}
func (def *defMeth) prinOut() {
    fmt.Println("just print: ", def)
}

type defError struct {
    err error
    str string
}

func (def *defError) ini() {
    def.err = fmt.Errorf("this is an err: %s\n", "true")
    def.str = "this is a bug"
}
func (def *defError) prinOut() {
    fmt.Println("just print: ", def)
}
func main() {
    var s1 defMeth
    var s2 defError
    var def in
    a := 1
    //defer+闭包处理, a为主函数变量,a值变化该defer函数变量会更新
    defer func() { fmt.Println("close package, test the value of a:", a) }()
    defer fmt.Println("fmt a is: ", a)
    //值传递,defer函数入栈,变量值已赋值,只是最后执行
    defer func(a int) { fmt.Println("no name func a is: ", a) }(a)
    //地址传递:传递的为地址,若地址处值改变则操作值改变,map传递的地址
    defer func(a *int) { fmt.Println("no name func a address is: ", *a) }(&a)
    //为接口赋值变量类型及变量地址
    def = &s1
    //a:=1
    def.ini()
    //defer a=2 //错误defer后必须是函数或者方法或者接口
    def.prinOut()
    //fmt.Println("result", bigSlowOperation())
    //接口
    def = &s2
    def.ini()
    //函数中嵌套defer改变defer执行顺序,函数中defer按栈执行,该函数正常执行
    def.prinOut()
    a++
    fmt.Println(a)
    fmt.Println("the value of bigSlow func: ", bigSlowOperation())
    //10 test defer panic
    deferPanic()

}
func bigSlowOperation() int {
    log.Printf("main starts %s", "\n")
    i := 1
    //非匿名函数调用参数i已确定:1
    //defer fmt.Println(i)
    //匿名函数可调用返回值:2
    defer func() { fmt.Println(i) }()
    defer trace("bigSlowOperation")() // don't forget the
    //extra parentheses
    // ...lots of work…
    time.Sleep(10 * time.Second) // simulate slow operation
    //by sleeping
    i++
    return i
}

//返回值为函数,函数需要正常入栈,
//函数输入参数及返回地址按正常函数处理,
//defer trace("")()
//函数为trace中包装的匿名函数,需正常处理该函数,
//的形参及返回地址
func trace(msg string) func() {
    start := time.Now()
    log.Printf("enter %s", msg)
    return func() {
        log.Printf("exit %s (%s)", msg, time.Since(start))
    }
}
//10 defer+panic: what happends after a defer func panic
func deferPanic() {
    //正常执行
    defer fmt.Println("the last defer panic func")
    defer fmt.Println("the 3st defer panic func")
    //panic func 仅执行panic语句
    defer func() { panic("test defer panic"); fmt.Println("the func panics") }()
    //正常执行
    defer fmt.Println("the 2st defer panic func")
    defer fmt.Println("the 1st defer panic func")
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构与算法

数据结构与算法

BrunoRPreiss / 电子工业出版社 / 2003-1 / 55.00元

本书是作者根据他在滑铁卢大学计算机工程学院教授数据结构与算法课程的经验编写而成的。它采用C++面向对象的设计模式,不仅系统全面地介绍了各种传统的数据结构,还把它们按照类和类层次的现代理念予以展开,进而达到抽象结构与实际设计的完美统一。本书的后三章通过引入抽象问题求解的概念,集中讲述了算法技术和各算法之间的关系。另外,作者运用一定的数学工具以及必要的分析技术和分析理论,对每种数据结构及相关算法都进行一起来看看 《数据结构与算法》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具