函数function
- Go 函数 不支持 嵌套、重载和默认参数
但支持以下特性:
- 无需声明原型、不定长度变参、多返回值、命名返回值参数
- 匿名函数、闭包
定义函数使用关键字 func,且左大括号不能另起一行
- 函数也可以作为一种类型使用
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- fmt.Println(A(1,"a"))
-
- fmt.Println(B(2,"b"))
-
- a,b,c := 1, 2, 3
- C("y",a,c)
- fmt.Println(a,c)
-
- arr := []int{1, 3, 4, 5, 6}
- D(arr)
- fmt.Println(arr)
-
- e := 2
- E(&e)
- fmt.Println(e)
-
- }
-
- func A(a int,b string) (int,string) {
- return a,b
- }
-
- func B(a int,b string) (A int,B string) {
- A,B = a,b
- return
- }
-
- //不定长变参,只能作为最后一个参数 而且拷贝的都是值拷贝
- func C(x string,a ...int) {
- a[0] = 4
- a[1] = 5
- a[2] = 6
- fmt.Println(x,a)
- }
-
- //数组的话都是地址拷贝
- func D(a []int) {
- a[0] = 10
- a[1] = 11
- a[2] = 12
- fmt.Println(a)
- }
-
- //如果 值拷贝 想更改为 地址拷贝
- //传参数的时候加上 &
- //方法形参加上 *
- func E(e *int) {
- *e = 9
- fmt.Println(*e)
- }
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- //匿名函数
- a := func() {
- fmt.Println("Func A")
- }
- a()
-
- fmt.Println()
-
- //匿名函数+闭包
- f := test(10)
- fmt.Println("------------------------")
- fmt.Println(f(1))
- fmt.Println(f(2))
-
- }
-
- func test(x int) func(int) int {
- fmt.Printf("%p,%d\n",&x,x)
- return func(y int) int {
- fmt.Printf("%p,x)
- return x + y
- }
- }
defer
- 执行方式类似其它语言中的析构函数,在函数体执行结束后
- 按照调用顺序的相反顺序逐个执行
- 即使函数发生严重错误也会执行
- 支持匿名函数的调用
- 常用于资源清理、文件关闭、解锁以及记录时间等操作
- 通过与匿名函数配合可在return之后修改函数计算结果
- 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer
- 时即已经获得了拷贝,否则则是引用某个变量的地址
- Go 没有异常机制,但有 panic/recover 模式来处理错误
- Panic 可以在任何地方引发,但recover只有在defer调用的函数中有效,而且得在panic前面
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- fmt.Println("a")
- defer fmt.Println("b")
- defer fmt.Println("c")
-
- fmt.Println("------------------")
-
- for i := 0; i < 3; i++ {
- defer func() {
- fmt.Println(i)
- }()
- }
- fmt.Println("---------------")
- }
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- A()
- B()
- C()
- }
-
- func A() {
- fmt.Println("func A")
- }
-
- func B() {
- panic("panic in B")
- }
-
- func C() {
- fmt.Println("func C")
- }
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- A()
- B()
- C()
- }
-
- func A() {
- fmt.Println("func A")
- }
-
- func B() {
- defer func() {
- if err := recover(); err != nil {
- fmt.Println("recover in B")
- }
- }()
- panic("panic in B")
- }
-
- func C() {
- fmt.Println("func C")
- }
- package main
-
- import (
- "fmt"
- )
-
- func main() {
- var fs = [4]func(){} //声明一个function类型的slice,长度为4
-
- for i := 0; i < 4; i++ {
- defer fmt.Println("defer i= ",i) //这是一个i作为参数传进去的输出,因为i是int型,所以遵循一个规则值拷贝的传递,还有defer是倒序执行的,所以先后输出3,2,1,0,跟下面的defer交替执行4次
- defer func() { fmt.Println("defer_closure i = ",i) }() //执行完下面的代码后,到了该defer了,这也是一个匿名函数,同样的也没有参数,也没有定义i,所以这也是个闭包,用的也是外面的i,所以先输出4,接着执行上面的defer,这样反复执行4次
- fs[i] = func() { fmt.Println("closure i = ",i) } //把相应的4个匿名函数存到function类型的slice里,因为这是个匿名函数,又没有参数,且也没有定义i,所以i就是外层函数的地址引用,就是for循环的i的地址,执行完for后i的值为4,所以输出4个4
- }
-
- for _,f := range fs { //用for循环对slice的调用,f为slice的值,即匿名函数,而f()则是对匿名函数的调用
- f()
- }
- }