go学习笔记3

defer:defer的功能是将它修饰的代码或者代码块延迟执行,推迟到当前函数的结束,并且如果有多行被defer,会倒序执行。

fmt.println("start")
defer fmt.println(1)
defer fmt.println(2)
defer fmt.println(3)
fmt.println("end")

这段代码的输出是

start
end
3
2
1

除过单行,defer也可以修饰匿名函数

defer func()int{
fmt.println(1)
fmt.println(2)
fmt.println(3)  //内部是顺序执行

return 3
}()        //别忘了立即执行

 

defer的效果是把代码推迟到return之后才执行。但是,对于”匿名函数立即执行“修饰defer,则分两种情况:

如果返回值没有提前命名:

func f1() int{
   var a int //0
  defer func(){
      a++
  }()   //立即执行标记,但是受defer影响
   return a   //还是0
}

但是,如果命名返回值,匿名函数就可以影响返回值

func f2() (a int){   //命名了返回值
   a = 0
  defer func(){
      a++
  }()   //立即执行, 也影响了外侧值
   return a   //1  不写a也行
}

go的return语句不是原子操作。不提前声明返回值,a就会立即被拷贝作为返回值传出,后续才执行的defer影响不到。如果提前声明了,那么a就是栈变量,defer可以直接影响到。

 此外,defer修饰函数时,虽然函数会被推迟,但函数参数都要立即确定,也就是冻结了当前值,后续的影响不改变函数。

i :=0
defer fmt.println(i)   //虽然defer,但打印0,不是1
i++

再据这个例子:

 对于两个defer,注册顺序是先上后下,执行顺序则是先下后上。

由于注册是从上到下,而注册时延迟函数的参数都要确定。

所以calc("A",x,y)先执行  。   打印A 1 2 3

然后是calc("B",x,y)    打印 B 10 2 12

然后是执行顺序,calc("BB",x,calc("B",x,y))     打印BB 10 12 22

最后是calc("AA",x,calc("A",x,y))    打印AA 1 3 4

注意目前提到的都是值类型,切片等引用类型还会有区别

 

------- -------

panic和recover,panic可以在任何地方抛出异常,在同函数内靠前位置defer一个匿名函数,用一个变量承接recover()如果没报错那err就是nil。

 go有errors这个包,此外error本身也是一个类型

posted @ 2025-07-06 16:58  namezhyp  阅读(8)  评论(0)    收藏  举报