4.函数变量的作用域
局部变量覆盖全局变量就近原则
package main var temp int = 200 func main() { temp := 100 if b := 1; b <= 100 { // 值;条件 temp := 50 println("内部的temp->", temp) //局部变量遵循就近原则 println("if语句的b->", b) } println("外部的temp->", temp) }
5.递归函数 (自己调用自己)
定义: 一个函数自己调用自己,就叫做递归函数。
注意: 递归函数需要有一个出口,组件向出口靠近,没有出口就会形成死循环
利用递归函数求和
package main func getSum(n int) int { if n == 1 { //当n等于1的时候,那个函数就变成一个值了。不具有回调函数了。 return 1 } return getSum(n-1) + n } func main() { println("值是:", getSum(5)) }
6.延迟函数(defer)
defer函数或方法: 一个函数或方法的执行被延迟了。
- 我们可以在函数中添加多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数的返回特别是当你在运行一些打开资源的操作时,遇到错误需要提前返回.在返回前,我们需要关闭相应的资源,不然容易造成资源泄露等问题。
- 如果有很多调用defer,那么defer是采用先进后出(栈)模式、
defer 函数名()
package main func f(s string) { println(s) } func main() { f("1") println(2) defer f("3") //会被延迟到最后执行 println(4) defer f("6") }
只是最后执行,但参数已经进去了
package main func f(a int) { println(a) } func main() { a := 10 println("a=", a) defer f(a) //参数已经传递进去了,只是在最后执行。 a++ println("end a=", a) }
(九)、函数的数据类型 (进阶)
1.函数类型的变量
var f3 func(int, int) int = f2
地址是一样的定义一个函数类型的函数变量
package main import "fmt" func f() { } func f1(int, int) { } func f2(a, b int) int { return a + b } // func()本身就是一个数据类型,如何定义一个函数类型的函数变量 func main() { fmt.Printf("%T\n", f) // func() fmt.Printf("%T \n", 100) // int fmt.Printf("%T\n", f1) // func(int, int) fmt.Printf("%T\n", f2) // func(int, int) int // 定义一个函数类型的变量 var f3 func(int, int) int = f2 //那么f3就有了f2的功能 println(f3(1, 2)) //拥有了函数2的功能。 // 地址一样 fmt.Printf("%p\n", f3) fmt.Printf("%p", f2) }
2.匿名函数推导
- 匿名函数可以作为另一个函数的值
- 匿名函数可以自己调用自己
- 匿名函数可以具有返回值
func(){ }()
package main func f() { println("我是f函数") } // func()本身就是一个数据类型,如何定义一个函数类型的函数变量 func main() { f() f2 := f // 不加括号就是变量,加括号就是调用 f2() // 匿名函数 第一种 f3 := func() { println("我是f3函数") } f3() // 如果是匿名函数的话,我们在后面写一个() ,那么就可以自己调用自己.可以有参数和返回值 第二种 func(a, b int) { println(a, " ", b) println("我是f4函数") }(1, 2) // 匿名函数也可以有返回值 第三种 f5 := func(a, b int) int { return a + b }(1, 2) println("我是f5函数", f5) }
3.函数式编程
高阶函数: 根据go语言的数据类型特点,可以将一个函数作为另外一个函数的参数。
func1(), func2() 将fun1函数作为fun2这个函数的参数 fun2函数: 就叫做豪杰函数,接受一个函数作为参数的函数 fun1函数: 就叫做回调函数,作为另外一个函数的参数
package main func add(a, b int) int { return a + b } // 高阶函数 -> 调用函数 func oper(a, b int, c func(int, int) int) int { x := c(3, 4) //在这里面进行赋值 return a + b + x } func oper2(a, b int, c func(int, int) int) int { x := c(3, 4) return a + b + x } // func()本身就是一个数据类型,如何定义一个函数类型的函数变量 func main() { println(add(1, 2)) // 打印一个普通函数 println(oper(1, 2, add)) //高阶函数 println(oper2(1, 2, func(a, b int) int { // 高阶函数- 匿名函数传入 return a + b })) //高阶函数 }
4.闭包
一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量并且该外层函数的返回值就是这个内层函数。这个内层函数和外层函数的变量,统称为闭包结构。.
局部变量的生命周期就会发生改变,正常的局部变量会随着函数的调用而创建,随着函数的结构而销毁。但是闭包结构中的外层函数的局部变量并不会随着外层函数的结果而销毁,因为内层函数还在继续使用。
package main // 自增 func increment() func() int { // 返回的类型是 函数类型,函数类型再返回整形 i := 0 // 闭包结构************************ // 定义一个匿名函数,给变量自增并返回 fun := func() int { // 内层函数,没有执行 i++ return i } return fun } func main() { f := increment() //这里时调用函数,不是赋值函数类型 -> 新建内存 println(f) v1 := f() // 开始自增 println(v1) v2 := f() //在原有的基础上继续自增 println(v2) f2 := increment() //这里时调用函数,不是赋值函数类型 ->新建内存 println(f2) v3 := f2() println(v3) // 从1开始 println(f()) // 调用f,在原有的内存上继续新增 println(f2()) // 调用f2,在原有的内存上继续新增 }