这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
函数式编程
函数的数据类型
func()本身就是一个数据类型
函数的本质
// func()本身就是一个数据类型
func main() {
//f1如果不加括号,函数就是一个变量
//f1() 如果加了括号那就成了函数的调用
fmt.Printf("%T\n", f1) //func()
fmt.Printf("%T\n", f2) //func(int, int)
fmt.Printf("%T\n", f3) //func(int, int) int
fmt.Printf("%T\n", 10) //int
//定义函数类型的变量
var f4 func(int, int)
f4 = f2 //引用类型
fmt.Println(f2) //0xbcff40
fmt.Println(f4) //0xbcff40 地址一样
f4(1, 2)
}
func f1() {
}
func f2(a, b int) {
fmt.Println(a, b)
}
func f3(a, b int) int {
return a + b
}
匿名函数的推导
```
func main() {
c1()
c2 := c1 //函数本身也是一个变量
c2()
//匿名函数
c3 := func() {
fmt.Println("我是c3函数")
}
c3()
//匿名函数自己调用自己,可以传参数的
func() {
fmt.Println("我是c4函数")
}()
func(a, b int) {
fmt.Println(a, b)
fmt.Println("我是c5函数")
}(1, 2)
r := func(a, b int) int {
return a + b
}(1, 2)
fmt.Println(r)
}
func c1() {
fmt.Println("我是c1函数")
}
```
### 回调函数

```
func main() {
r1 := add1(1, 2)
fmt.Println(r1)
r2 := oper(1, 3, add1)
fmt.Println(r2)
r3 := oper(1, 3, sub1)
fmt.Println(r3)
r4 := oper(8, 4, func(a int, b int) int {
if b == 0 {
fmt.Println("除数不能为0")
return 0
}
return a / b
})
fmt.Println(r4)
}
// 高阶函数,可以接受一个函数作为参数
func oper(a, b int, fun func(int, int) int) int {
r := fun(a, b)
return r
}
// 回调函数
func add1(a, b int) int {
return a + b
}
func sub1(a, b int) int {
return a - b
}
```
### 闭包结构

```
func main() {
r1 := increment()
fmt.Println(r1) //0x106e620
v1 := r1()
fmt.Println(v1) //1
v2 := r1()
fmt.Println(v2) //2
fmt.Println(r1()) //3
fmt.Println(r1()) //4
r2 := increment()
v3 := r2()
fmt.Println(v3) //1
fmt.Println(r1()) //5
fmt.Println(r2()) //2
}
func increment() func() int {
//局部变量i
i := 0
//定义一个匿名函数,给自变自增并且返回
fun := func() int { //内层函数,没有执行的
i++
return i
}
return fun
}
```
**闭包缺点**
因为闭包会携带包含它的函数的作用域,所以哪怕外部函数执行完成,因为内部函数保存了外部函数中变量的引用,所以外部函数依然不会被释放,所以过度使用闭包会造成内存占用过多。