关于go:上篇Go函数的骚包玩法有哪些

1. 用type关键字能够定义函数类型,函数类型变量能够作为函数的参数或返回值。

package main

import "fmt"

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

func sub(a, b int) int {
    return a - b
}

type Task func(int, int) int

func exec(t Task, a, b int) int {
    return t(a, b)
}

func main() {
    a := exec(add, 10, 20)
    fmt.Println(a)

    b := exec(sub, 100, 95)
    fmt.Println(b)
}

解析:type Task func(int, int) int,这句是说,应用type关键字定义1个类型为func的Task,这个func有2个int形参、1个int返回值。再看exec这个函数,它有3个形参,形参t的类型是刚定义的函数类型Task,另外两个你懂的,我就不说了。

2. 匿名函数的玩法是真的骚,看看骚在哪里

  • 栗子1:匿名函数能够间接赋给变量

    func main() {
      var aaa = func(a, b int) int {
          return a + b
      }
      ret := aaa(89, 78)
      fmt.Println(ret)
    }

    输入:

    167
  • 栗子2:匿名函数作为函数入参

    这个例子感觉跟方才应用type关键字定义函数类型的例子有点雷同的赶脚,认真一看,如同也只是在应用的形式上是一样,定义函数的套路又是不同的。

    func work(f func(int, int) int, a, b int) int {
      return f(a, b)
    }
    
    func add(a, b int) int {
      return a + b
    }
    
    func main() {
      a := work(add, 100, 200)
      fmt.Println(a)
    }

    输入:

    300

    解析:形参f的类型就是匿名函数,持续看func(int, int) int,这个匿名函数接管两个int形参,返回值也是int类型。另外两个形参a和b,也是int,想必你懂了,我就不废话了。

  • 栗子3:匿名函数作为函数出参

    匿名函数作为函数出参(作为函数返回值),经一直调测,有3种骚包玩法,爽死了。

  1. 骚包玩法1

    // 先来个简略的
    func work() func() int {
     return func() int {
         return 10 + 20
     }
    }
    
    func main() {
     f := work()
     ret := f()
     fmt.Println(ret)
    }

    输入:

    30
  2. 骚包玩法2

    // 再革新下
    func work(a, b int) func() int {
     return func() int {
         return a + b
     }
    }
    
    func main() {
     f := work(500, 20)
     ret := f()
     fmt.Println(ret)
    }

    输入:

    520
  3. 骚包玩法3

    // 再次革新
    func work() func(int, int) int {
     return func(a, b int) int {
         return a + b
     }
    }
    
    func main() {
     f := work()
     ret := f(600, 50)
     fmt.Println(ret)
    }

    输入:

    650
  4. 对3种骚包玩法的简略解析:

    再这里就解析一下第3种玩法,能搞懂这个玩法,后面2个玩法,你就天然懂了。work函数没有入参,然而有出参(也能够说是返回值),出参是匿名函数func(int, int) int,这个定义在返回值里的匿名函数有2个int类型的形参(入参)和1个int类型的返回值。再看看函数体外部,没干很简单活儿,而是间接return了匿名函数,函数体里的这个匿名函数是和定义在返回值里的类型保持一致的,也是接管了2个int的形参a和b,返回值也是int,啥也没干,就做了个相加。好郁闷!不晓得你看懂了没?再看看是如何应用work函数的,关键点就在这里,调用work()赋给了变量f,这时候,f它就是一个函数了,再调用f(600, 50),想必你曾经晓得了为啥要传入2个int值,这下搞定!不晓得把你绕晕没,这玩法的确很骚。

3. 匿名函数和提早调用

提早调用的规定是:依照先进后出的程序,也就是说函数返回前是会被执行的,而且是依照先进后出的程序。如何起到提早的成果,是须要注册的,可通过defer关键字进行注册。那么什么场景下须要用到提早调用呢?比方常见的场景:当一个函数被行将执行完后,也就是实现工作的最初一刻,须要回收和开释某些资源。

提早调用的机制能够配合匿名函数来应用,这样就能够让匿名函数被间接调用,只能说是真的骚。

先看个小栗子:

package main

import "fmt"

func work() bool {
    fmt.Println("函数开始工作...")
    defer func() {
        fmt.Println("回收相干资源工作开始!")
    }()
    defer func() {
        fmt.Println("清理工作开始!")
    }()
    fmt.Println("函数正在工作...")
    fmt.Println("函数工作结束...")
    return true
}
func main() {
    status := work()
    fmt.Println(status)
}

输入:

函数开始工作...
函数正在工作...
函数工作结束...
清理工作开始!
回收相干资源工作开始!
true

在下面的栗子中,定义了个work函数,先看看输入的后果,感触下。在work函数中,注册了两个提早调用,work函数从开始->正在->结束,完结后才执行defer注册的匿名函数,这里要着重留神提早调用规定:先进后出,也就是先注册后执行。“回收相干资源工作”是先注册的,他的执行程序排在了“清理工作”的前面。感触到了吗?

最初阐明一下:defer关键字让匿名函数实现了可间接调用,那么应用defer注册提早调用时要留神,defer关键字的前面肯定是要函数或办法的调用,不能间接写语句哦。

本文转载于(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/Dt…

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理