10 Go匿名函数 && 闭包

2018-10-30  本文已影响0人  亨锅锅

1、函数的基本规则

package main

import "fmt"

func main() {
    /*
    1.C语言是由函数组成的
    2.Go语言也是由函数组成的
    3.C语言函数的格式
    返回值类型 函数名称(形参列表){
        被控制的语句;
    }
    4.Go语言函数的格式
    func 函数名称(形参列表)(返回值列表){
        被控制的语句;
    }

    5.C语言函数的类型
    5.1没有返回值没有形参的函数
    5.2有返回值没有形参的函数
    5.3没有返回值有形参的函数
    5.4有返回值有形参的函数

    6.Go语言函数的类型和C语言一样

    注意点:
    1.在C语言中如果函数的定义写在函数的调用之前必须先声明再调用
    在Go语言中如果函数的定义写在函数的调用之前, 不用声明就可以调用, Go语言没有声明
    2.Go语言中如果函数只有一个返回值, 那么返回值列表的()可以省略
    3.Go语言中如果有返回值, 可以在返回值列表中定义变量, 然后在函数体中直接使用
    4.如果在返回值列表中定义了变量,  那么return后面可以不用写任何内容, 默认就会将返回值列表中定义的变量返回
    5.Go语言中一个函数可以有多个返回值
    6.如果一个函数有多个返回值, 但是我们只想使用其中的一个, 那么可以在接收的时候使用_来忽略, 不需要的那个返回值
    7.因为_在Go语言中有特殊的含义, 所以在定义标识符的时候_不能单独作为标识符
    8.如果返回值列表中有多个返回值, 并且连续的多个返回值的数据类型都一样, 那么只用在最后一个变量后面添加数据类型即可
    9.如果形参列表中有多个形参, 并且连续的多个形参的数据类型都一样, 那么只用在最后一个变量后面添加数据类型即可
     */
    //say()
    //res := getNumber()
    //fmt.Println(res)

    //a, b := getValue()
    //fmt.Println("a = ", a, "b = ", b)
    //a, _ := getValue()
    //fmt.Println("a = ", a)

    //sum(10, 20)

    res := minus(10, 20)
    fmt.Println(res)
}
// 1.没有返回值没有形参的函数
func say(){
    fmt.Println("没有返回值没有形参")
}
// 2.有返回值没有形参的函数
// 2.1只有一个返回值的函数
//func getNumber()(int){
//func getNumber()int{
//  return 888
//}
func getNumber() (num int){
    num = 999
    return
}
// 2.2有多个返回值的函数
//func getValue() (int, int){
//  return 666, 888
//}
//func getValue() (num int,value int){
func getValue() (num ,value int){
    //num = 666
    //value = 888
    //return
    return 666, 888
}
//func test()(num int, temp float64, value int){
//func test()(num , value int, temp float64){
//
//}

// 3.没有返回值有形参的函数
//func sum(a int, b int){
func sum(a , b int){
    res := a + b
    fmt.Println(res)
}

// 4.有返回值有形参的函数
//func minus(a, b int)(res int){
//  res = a - b
//  return
//}

func minus(a int, b int)(int){
    res := a - b
    return res
}

2、函数的参数

package main

import "fmt"

func main() {
    /*
    1.在C语言中如果基本数据类型作为函数的参数, 是值传递, 在函数内修改形参不会影响到外界的实参
    2.Go语言和C语言一样/ int float bool

    3.如果想在函数内部修改外界传入的实参, 那么必须传入指针
     */
    num := 666
    fmt.Println(num)
    //change1(num)
    change2(&num)
    fmt.Println(num)
}
func change1(a int) {
    a = 789
}

func change2(a *int) {
    *a = 789
}

3、什么是匿名函数

package main

import "fmt"

func main() {
    /*
    1.什么是匿名函数?
    普通的函数都是有名字的函数, 而匿名函数就是没有名字的函数

    2.匿名函数的应用场景:
    一般情况下某个函数只会被调用一次, 我们就会使用匿名函数
    作为函数的参数, 或者作为函数的返回值

    3.注意点:
    3.1匿名函数定义之后, 如果没有立即调用, 编译器会报错
    3.2也可以将一个匿名函数保存到一个变量中
    在C语言中我们知道, 我们可以定义一个指向函数的指针来保存函数的地址, 然后通过指针来调用函数
    在Go语言中函数是一等公民(可以定义变量, 作为形参, 作为返回值), 所以在Go语言中也可以用函数类型来定义变量(相当于C语言中指向函数的指针)
    3.3由于函数是一等公民, 所以以前定义变量所有的格式, 都可以用于定义函数类型的变量
    var 变量名称 函数类型
    var 变量名称 函数类型 = 匿名函数
    var 变量名称  = 匿名函数
    变量名称  := 匿名函数
    var(
        var 变量名称  = 匿名函数
    )

    C语言中指向函数的指针
    int test(int a, int b){}
    int (*test)(int, int)
     */
     // test相当于找到函数的定义, 然后调用函数
     test()

     // 直接定义一个函数, 然后立即调用这个函数
     //func(){
     // fmt.Println("匿名函数")
     //}()

     // 定义一个函数类型的变量, 保存匿名函数, 然后通过函数类型的变量调用匿名函数
     //f := func() {
        // fmt.Println("匿名函数")
     //}
     var f func() = func() {
         fmt.Println("匿名函数")
     }
     //fmt.Printf("%T\n", f)
     f()
}

func test(){
    fmt.Println("test")
}

4、匿名函数的应用

4.1

package main

import "fmt"

func main() {
    /*
    1.作为其他函数的参数
    2.作为其他函数的返回值
     */
     /*
     res1 := sum(10, 20)
     res2 := minus(10, 20)
     fmt.Println(res1)
     fmt.Println(res2)
     */

     // 需求: 定义一个匿名函数, 实现两个数相加
    //fn := func(a, b int) int {
    //  return  a + b
    //}
    //fmt.Printf("%T\n", fn)

    //相当于如下:
    //var fn func(int, int) int = func(a, b int) int {
    //  return  a + b
    //}
    //res := fn(10, 20)
    //fmt.Println(res)

    //var method func(int, int) int = fn
    //res := method(10, 20)
    //fmt.Println(res)

    //匿名函数的赋值 和 变量的使用 类比如下
    //var num int = 6
    //var value int = num
    //fmt.Println(value)

    //result := calculate(10, 20, fn)

    result := calculate(10, 20, func(a, b int) int {
        return  a + b
    })
    fmt.Println(result)
}
func calculate(a, b int, method func(int, int) int) (int) {
    res := method(a, b)
    return res
}

func sum(a, b int) int {
    return  a + b
}
func minus(a, b int) int {
    return  a - b
}

4.2

package main

import "fmt"

func main() {

    // 1.匿名函数作为函数的参数
    /*
    //var fn func()
    //fn = func() {
    //  fmt.Println("匿名函数")
    //}
    //fmt.Printf("%p\n", fn)
    //test(fn)

    test(func() {
        fmt.Println("匿名函数")
    })
    */
    /*
    var fn func()
    fn = test()
    fn()
    */

    //2.作为其他函数的返回值
    var fn func(int, int)int
    fn = test()
    res := fn(10, 20)
    fmt.Println(res)
}

func test()func(int, int)int{
    return func(a int, b int)int {
        return a + b
    }
}


//func test() func() {
//  return func() {
//      fmt.Println("匿名函数")
//  }
//}

//func test(method func())  {
//  fmt.Printf("%p\n", method)
//  method()
//}

4.3、

package main

import (
    "fmt"
)

func main() {

    //work(func() {
    //  fmt.Println("参与部门会议")
    //  fmt.Println("修改BUG")
    //  fmt.Println("完成老大安排的任务")
    //  fmt.Println("... ...")
    //  fmt.Println("提交代码")
    //})

    work(func() {
        fmt.Println("组织部门会议")
        fmt.Println("给部门的员工分配任务")
        fmt.Println("检查部门员工昨天提交的代码")
        fmt.Println("... ...")
    })
}
// 攻城狮的一天
func work(method func()){
    // 1.上班前
    func(){
        fmt.Println("起床")
        fmt.Println("刷牙洗脸")
        fmt.Println("吃早餐")
        fmt.Println("做地铁")
        fmt.Println("打卡")
        fmt.Println("打开电脑")
    }()

    // 2.上班中
    method()

    // 3.下班之后
    func(){
        fmt.Println("关电脑")
        fmt.Println("打卡")
        fmt.Println("坐地铁")
        fmt.Println("到家")
        fmt.Println("吃饭")
        fmt.Println("娱乐")
        fmt.Println("刷牙洗脸")
        fmt.Println("睡觉")
    }()

}

// 项目经理的一天
func work2(){
    fmt.Println("起床")
    fmt.Println("刷牙洗脸")
    fmt.Println("吃早餐")
    fmt.Println("做地铁")
    fmt.Println("打卡")
    fmt.Println("打开电脑")

    fmt.Println("组织部门会议")
    fmt.Println("给部门的员工分配任务")
    fmt.Println("检查部门员工昨天提交的代码")
    fmt.Println("... ...")

    fmt.Println("关电脑")
    fmt.Println("打卡")
    fmt.Println("坐地铁")
    fmt.Println("到家")
    fmt.Println("吃饭")
    fmt.Println("娱乐")
    fmt.Println("刷牙洗脸")
    fmt.Println("睡觉")
}
// 程序员的一天
func work1()  {
    fmt.Println("起床")
    fmt.Println("刷牙洗脸")
    fmt.Println("吃早餐")
    fmt.Println("做地铁")
    fmt.Println("打卡")
    fmt.Println("打开电脑")

    fmt.Println("参与部门会议")
    fmt.Println("修改BUG")
    fmt.Println("完成老大安排的任务")
    fmt.Println("... ...")
    fmt.Println("提交代码")

    fmt.Println("关电脑")
    fmt.Println("打卡")
    fmt.Println("坐地铁")
    fmt.Println("到家")
    fmt.Println("吃饭")
    fmt.Println("娱乐")
    fmt.Println("刷牙洗脸")
    fmt.Println("睡觉")
}

5 闭包

package main

import "fmt"

func main() {
    /*
    1.什么是闭包?
    闭包就是一个特殊的匿名函数
    只要匿名函数中用到了外界的变量, 那么我们就把匿名函数叫做闭包

    注意点:
    只要闭包还在使用外界的变量, 那么外界的变量就会一直存在
     */

     /*
     num := 10 // 11 12
     a := func() {
        num++
        fmt.Println(num)
     }
     a() // 11
     a() // 12
     a() // 13
     */
     // addUpper会返回一个闭包, 那么fn中保存的就是这个闭包, 那么fn就等于闭包
     // 所以按照Go语言的规则, 只要fn还在, addUpper中被闭包引用的变量就不会释放
     fn := addUpper()
     fn()
     fn()
     fn()
}
func addUpper() func() {
    x := 1
    return func() {
        x++
        fmt.Println(x) // 2 , 3 , 4
    }
}
上一篇 下一篇

猜你喜欢

热点阅读