zoukankan      html  css  js  c++  java
  • golang匿名函数(闭包)

    GO语言的匿名函数(anonymous function),
    其实就是闭包.是指不需要定义函数名的一种函数实现方式..
     可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的作用域.
     闭包的价值:闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。
     先看个例子:

    package main
    
    import "fmt"
    
    func f()(ret int) {
    defer func() {
    ret++
    }()
    return 1
    }
    
    func main() {
    fmt.Println(f())
    }
    ----------
    //输出结果 : 2
    

      


      变量ret的值为 2 ,这是因为在执行return 1 语句的时候执行了ret++

    1 . 匿名函数定义:
     匿名函数由一个不带函数名的函数声明和函数体组成,如下所示:

    func(a,b int,z float64) bool{
    return a*b
    }


     匿名函数只是作为一个表达式,那是非常没有意义的。匿名函数可以直接赋给一个变量,作为结构字段,或者把它传递到另外的函数当中或者直接执行。常常看到以下这种类型的代码出现在go中:

    //function variable
    fn := func(){
    fmt.Println("hello")
    } 
    fmt.Printf("%T
    ",fn) //打印func()


     我们现在有一个变量fn,它是一个function;它的类型是func()。它能像其他的任何函数一样被调用,通过表达fn(),或者赋值给你感兴趣的其他func()。

     另外一种情况,即声明时指定了参数接收列表。

    fn:= func(a,b int,z float64) bool{
    return a*b
    }
    fmt.Printf(“%T
    ”,fn) //打印fn的类型,
    //即func(int, int, float64) bool


     定义一个匿名函数并调用(该函数)执行(ps:若匿名函数在声明时指定了参数接收列表,那么在调用执行时,也必须带上参数列表传进去,否则会出现编译错误):

    func() {
    //func body
    }() //花括号后加()表示函数调用,此处声明时为指定参数列表,
    //故调用执行时也不需要传参

    fun(a,b int) {
    fmt.Println(a+b)
    }(1,2) //打印3
     另外一种写法:

    fn := func(a, b int) {
    fmt.Println(a + b)
    }
    fn(1, 2)
    2 . 匿名函数用法
    —->函数集合
    fns:=[](func(x int) int){
    func(x int) int {return x+1},
    func(x int) int {return x+2},
    func(x int) int {return x+3},
    }
    fmt.Println(fns[0](1)) //fns[0]:函数变量


    ----------
    输出结果:
    fmt.Println(fns[0](1)) : 2


    ----------


    若打印:fmt.Println(fns[1](1)) : 3
    若打印:fmt.Println(fns[2](1)) : 4
    敲黑板!注意:
     fns[3]则会引发panic: runtime error: index out of range

    —->函数作为字段
    d := struct {
    fn func() string
    }{
    fn: func() string { return "Hello, World!" },
    }
    println(d.fn())
    —->函数通道
    fc := make(chan func() string, 2)
    fc <- func() string { return "Hello, World!" }
    println((<-fc)())
    3 .
      闭包复制的是原对象指针,这就很容易解释延迟引用现象

    func test() func() {
    x := 100
    fmt.Printf("x (%p) = %d ", &x, x)
    return func() {
    fmt.Printf("x (%p) = %d ", &x, x)
    } }
    func main() {
    f := test()
    f() }


    ----------
    输出:
    x (0x2101ef018) = 100
    x (0x2101ef018) = 100
      在汇编层面,test实际返回的是FuncVal对象,其中包含了函数地址,闭包对象指针..当调用匿名函数时,只需要以某个寄存器传递该对象即可.

    FuncVal { func_address, closure_var_pointer ... }
    1
    注:本文多处内容引用了 雨痕 的 [Go学习笔记.第四版]

  • 相关阅读:
    python中的编码与解码
    python中的迭代器
    python中高阶函数与装饰器(3)
    python中高阶函数与装饰器(2)
    python中高阶函数与装饰器
    python中几种常用的数据类型
    python 启航
    Python [习题] 字典排序
    SQL-TSQL
    SQL基础语句
  • 原文地址:https://www.cnblogs.com/cxy2020/p/14821698.html
Copyright © 2011-2022 走看看