GO入门——5. 函数

1 函数

  • Go 函数 不支持 嵌套、重载和默认参数

  • 定义函数使用关键字 func,且左大括号不能另起一行

  • 函数也可以作为一种类型使用

  • 无需声明原型

  • 不定长度变参

func A(a string,c ... int){
    //不定长变参必须在最后
    //此时c为一个slice
}
  • 多返回值
func A() (int,int){
    //返回多个int
}
  • 命名返回值参数
func A() (a int,b string){
    //此时a,b已经声明,直接给其赋值不需要return
    //也可以不管a,b,直接return别的
}
  • 匿名函数
func A(){
    a:=func (){
        fmt.Println("匿名函数")
    }
    a()
}
  • 闭包
func main() {
	s := []int{0, 1, 2}
	c := closure(s)     
	fmt.Println(c())    //输出0
	s[0] = 10
	fmt.Println(c())    //输出10
}
func closure(s []int) func() int {
	return func() int {
		return s[0]     //该s是传入slice的地址,因此后续使用将一直使用传入的slice
	}
}

2 defer

  • 执行方式类似其它语言中的析构函数,在函数体执行结束后
    按照调用顺序的相反顺序逐个执行
  • 即使函数发生严重错误也会执行
  • 支持匿名函数的调用
  • 常用于资源清理、文件关闭、解锁以及记录时间等操作
  • 通过与匿名函数配合可在return之后修改函数计算结果
  • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer
    时即已经获得了拷贝,否则则是引用某个变量的地址
/*输出顺序如下
j= 13
j= 13
j= 13
i= 2
i= 1
i= 0
*/
func funcDefer() {
	for i := 0; i < 3; i++ {
		defer fmt.Println("i=", i)  //defer按照栈顺序出入
	}
	for j := 10; j < 13; j++ {
		defer func() {
			fmt.Println("j=", j)    //传入闭包的j为地址,执行完函数后j=13,所以后续均为13
		}() //后面的括号表示调用这个匿名函数
	}
}


  • Go 没有异常机制,但有 panic/recover 模式来处理错误
  • Panic 可以在任何地方引发,但recover只有在defer调用的函数中有效
/*如果不使用recover()将输出
A
B
panic: B err
*/
/*使用recover()将输出
A
B
recover in B
C
*/
func pc() {
	A := func() {
		fmt.Println("A")
	}

	B := func() {
		fmt.Println("B")
		defer func() {
		    //recover相当于catch了异常,异常存入了err
			if err := recover(); err != nil {   
				fmt.Println("recover in B")
			}
		}()     
		panic("B err")  //相当于抛出异常
	}
	C := func() {
		fmt.Println("C")
	}

	A()
	B()
	C()

}
原文地址:https://www.cnblogs.com/suolu/p/6714732.html