1.1 函数的本质

在Go语言中,函数也是一种数据类型。

package main

import "fmt"

func main() {
    /*
    Go语言的数据类型:

数值类型:整数,浮点
            进行运算操作,加减乘除,打印
        字符串:
            可以获取单个字符,截取子串,遍历,strings包下的函数操作。。
        数组,切片,map。。
            存储数据,修改数据,获取数据,遍历数据。。。
        函数:
            加(),进行调用

注意点:
            函数作为一种复合数据类型,可以看做是一种特殊的变量。
                函数名():将函数进行调用,函数中的代码会全部执行,然后将return的结果返回给调用处

                函数名:指向函数体的内存地址

*/
     //1.整型
     a := 10
     //运算:
     a += 5
     fmt.Println("a:",a)
     //2.数组,切片,map。。容器
     b := [4]int{1,2,3,4}
     b[0] =100
     for i:=0;i 空

//var d  string
     //d = "hello"
     c = fun1 //将fun1的值(函数体的地址)赋值给c
     fmt.Println(c)

fun1(10,20)
     c(100,200) //c也是函数类型的,加小括号也可以被调用

res1 := fun2 //将fun2的值(函数的地址)赋值给res1,res1和fun2指向同一个函数体
     res2 := fun2(1,2) //将fun2函数进行调用,将函数的执行结果赋值给res2,相当于:a+b
     fmt.Println(res1)
     fmt.Println(res2)

fmt.Println(res1(10,20))//也可以被调用
     //res2() //cannot call non-function res2 (type int)
}
func fun2(a,b int)int{
    return a + b
}
func fun1(a, b int){
    fmt.Printf("a:%d,b:%d\n",a,b)
}
COPY

1.2 匿名函数

匿名函数:没有名字的函数。

定义一个匿名函数,直接进行调用。通常只能使用一次。也可以使用匿名函数赋值给某个函数变量,那么就可以调用多次了。

package main

import "fmt"

func main() {
    /*
    匿名:没有名字
        匿名函数:没有名字的函数。

定义一个匿名函数,直接进行调用。通常只能使用一次。也可以使用匿名函数赋值给某个函数变量,那么就可以调用多次了。

匿名函数:
        Go语言是支持函数式编程:
        1.将匿名函数作为另一个函数的参数,回调函数
        2.将匿名函数作为另一个函数的返回值,可以形成闭包结构。
     */
     fun1()
     fun1()
     fun2 := fun1
     fun2()

//匿名函数
     func (){
        fmt.Println("我是一个匿名函数。。")
     }()

fun3:=func(){
        fmt.Println("我也是一个匿名函数。。")
     }
     fun3()
     fun3()

//定义带参数的匿名函数
     func (a,b int){
        fmt.Println(a,b)
     }(1,2)

//定义带返回值的匿名函数
     res1 := func (a, b int)int{
        return a + b
     }(10,20) //匿名函数调用了,将执行结果给res1
     fmt.Println(res1)

res2 := func (a,b int)int{
        return a + b
     } //将匿名函数的值,赋值给res2
     fmt.Println(res2)

fmt.Println(res2(100,200))
}

func fun1(){
    fmt.Println("我是fun1()函数。。")
}
COPY

匿名函数:

Go语言是支持函数式编程:

1.将匿名函数作为另一个函数的参数,回调函数

2.将匿名函数作为另一个函数的返回值,可以形成闭包结构。

1.3 回调函数

回调函数:callback,就是将一个函数fun2作为函数fun1的一个参数。那么fun2叫做回调函数,fun1叫做高阶函数。

package main

import "fmt"

func main() {
    /*
    高阶函数:
        根据go语言的数据类型的特点,可以将一个函数作为另一个函数的参数。

fun1(),fun2()
    将fun1函数作为了fun2这个函数的参数。

fun2函数:就叫高阶函数
                接收了一个函数作为参数的函数,高阶函数

fun1函数:回调函数
                作为另一个函数的参数的函数,叫做回调函数。
     */
    //设计一个函数,用于求两个整数的加减乘除运算
    fmt.Printf("%T\n", add)  //func(int, int) int
    fmt.Printf("%T\n", oper) //func(int, int, func(int, int) int) int

res1 := add(1, 2)
    fmt.Println(res1)

res2 := oper(10, 20, add)
    fmt.Println(res2)

res3 := oper(5,2,sub)
    fmt.Println(res3)

fun1:=func(a,b int)int{
        return a * b
    }

res4:=oper(10,4,fun1)
    fmt.Println(res4)

res5 := oper(100,8,func(a,b int)int{
        if b == 0{
            fmt.Println("除数不能为零")
            return 0
        }
        return a / b
    })
    fmt.Println(res5)

}
func oper(a, b int, fun func(int, int) int) int {
    fmt.Println(a, b, fun) //打印3个参数
    res := fun(a, b)
    return res
}

//加法运算
func add(a, b int) int {
    return a + b
}

//减法
func sub(a, b int) int {
    return a - b
}
COPY

1.4 闭包

闭包(closure):

一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量(外层函数中的参数,或者外层函数中直接定义的变量),并且该外层函数的返回值就是这个内层函数。

这个内层函数和外层函数的局部变量,统称为闭包结构。

package main

import "fmt"

func main() {
    /*
    go语言支持函数式编程:
        支持将一个函数作为另一个函数的参数,
        也支持将一个函数作为另一个函数的返回值。

闭包(closure):
        一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量(外层函数中的参数,或者外层函数中直接定义的变量),并且该外层函数的返回值就是这个内层函数。

这个内层函数和外层函数的局部变量,统称为闭包结构。

局部变量的生命周期会发生改变,正常的局部变量随着函数调用而创建,随着函数的结束而销毁。
        但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还要继续使用。

*/
     res1 := increment() //res1 = fun
     fmt.Printf("%T\n",res1) //func() int
     fmt.Println(res1)
     v1 := res1()
     fmt.Println(v1) //1
     v2 := res1()
     fmt.Println(v2) //2
     fmt.Println(res1())
     fmt.Println(res1())
     fmt.Println(res1())
     fmt.Println(res1())

res2 := increment()
     fmt.Println(res2)
     v3 :=res2()
     fmt.Println(v3) //1
     fmt.Println(res2())

fmt.Println(res1())
}

func increment()func()int{ //外层函数
    //1.定义了一个局部变量
    i := 0
    //2.定义了一个匿名函数,给变量自增并返回
    fun := func ()int{ //内层函数
        i++
        return i
    }
    //3.返回该匿名函数
    return fun
}
COPY

闭包结构的注意点:局部变量的生命周期会发生改变,正常的局部变量随着函数调用而创建,随着函数的结束而销毁。但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还要继续使用。