09 函数function
函数function
Go 函数 不支持 嵌套、重载和默认参数
但支持以下特性:
无需声明原型、不定长度变参、多返回值、命名返回值参数
匿名函数、闭包
定义函数使用关键字 func,且左大括号不能另起一行
函数也可以作为一种类型使用
//最基本定义
func A(a int, b string){
}
//有返回值定义
func A(a int, b string) int {//返回一个值
}
func A(a int, b string) (int, string) {//返回多个值
a, b := 1 ,2
return a, b//这里reutrn 必须要填写2个
}
//扩展
func A(a , b , c int){//a b c 都是int类型
}
func A(a , b , c int)(d , e ,f int){//返回值偷懒写的话 就必须命名返回值
d, e ,f = 1, 2, 3 //这里不需要 := 因为前面d e f相当于已经初始化过了
return //这里不需要填写d,e,f之类的 为了可读性要求 最好还是加上d,e,f
}
//不定长变参
func A(b string, a ... int){//这个a参数必须放在所有参数的最后面
fmt.Println(a) //可以调用A(1,2,3,4,5,6)
}
//可以直接传整个slice进去 这样里面的代码的修改属于引用修改 如果一个个参数传进去是属于拷贝
匿名函数
//函数其实是属于一种数据类型
a :=A
a()//相当于A()
a:=func(){
fmt.Println("hello")
}
a()
闭包
func closure(x int) func(int) int{//返回一个匿名函数
return func(y int) int {
return x+y //这里x直接可以从外层函数拿这是闭包函数的特性
}
}
f := closeure(10)
fmt.Println(f(1))//输出11
fmt.Println(f(2))//输出12
//这里的x是引用 并不是拷贝值
defer
的执行方式类似其它语言中的析构函数,在函数体执行结束后
按照调用顺序的相反顺序逐个执行
即使函数发生严重错误也会执行
支持匿名函数的调用
常用于资源清理、文件关闭、解锁以及记录时间等操作
通过与匿名函数配合可在return之后修改函数计算结果
如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer
时即已经获得了拷贝,否则则是引用某个变量的地址
Go 没有异常机制,但有 panic/recover 模式来处理错误
Panic 可以在任何地方引发,但recover只有在defer调用的函数中有效
典例
for i := 0; i<3; i++{
defer fmt.Println(i)
}
//最后输出2 1 0
复杂化
for i := 0; i<3; i++{
defer func(){
fmt.Println(i)
}()//这里相当于定义一个func A 然后A()
}
//最后输出2 1 0
//制作异常机制
func main(){
A()
B()
C()
}
func A(){
fmt.Println("Func A")
}
func B(){
defer func(){//程序执行到panic的时候程序进入一个恐慌状态,然后defer开始执行,执行的函数中进行了recover()的检测 如果recover()!=nil
然后陈旭进行继续恢复操作
if err := recover();err!=nil{
fmt.Println("Func B")
}
}()
panic("Panic in B") //程序进入恐慌状态 程序执行到这里的时候就不执行了 相当于php中的die 如果没有进行恢复 之类的操作 将最后跳出panic in B 以及一些错误
}
func C(){
fmt.Println("Func C")
}