Go笔记(4) | 青训营笔记

58 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

函数式编程

函数的数据类型

image-20230115203840656

func()本身就是一个数据类型

函数的本质

image-20230115205422719

// 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
}

匿名函数的推导

image-20230115210130545


```
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函数")
}
```

### 回调函数

![image-20230115211611830](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b5b92bffe7b4fa29dc2de6da497133e~tplv-k3u1fbpfcp-zoom-1.image)

```
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
}
```

### 闭包结构

![image-20230115214258144](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/751ade44178649edafd8477ee85b5004~tplv-k3u1fbpfcp-zoom-1.image)

```
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
}
```
**闭包缺点**

因为闭包会携带包含它的函数的作用域,所以哪怕外部函数执行完成,因为内部函数保存了外部函数中变量的引用,所以外部函数依然不会被释放,所以过度使用闭包会造成内存占用过多。