golang 函数二 (匿名函数和闭包)

匿名函数就是没有定义函数名称的函数。我们可以在函数内部定义匿名函数,也叫函数嵌套。

匿名函数可以直接被调用,也可以赋值给变量、作为参数或返回值。比如:

func main(){
    func(s string){     //直接被调用
        println(s)
    }("hello gopher!!!")
    /*
    func(s string){     //未被调用
        println(s)
    }
    */
}

func main(){
    hi := func(s string){   //赋值给变量
        println(s)
    }
    hi("hello gopher!!!")
}

func test(f func(string)){
    f("hello gopher!!!")
}
func main(){
    hi := func(s string){
        println(s)
    }
    test(hi)     //作为参数
}

func test()func(string){
    hi := func(s string){   //作为返回值
        println(s)
    }
    return hi
}

func main(){
    f := test()
    f("hello gopher!!!")
}

普通函数和匿名函数都可以作为结构体的字段,比如:

{
    type calc struct{
        mul func(x,y int)int
    }
    x := calc{
        mul: func(x,y int)int{
            return (x*y)
        },
    }
    println(x.mul(2,3))
}

也可以经channel(通道)传递,比如:

{
    c := make(chan func(int, int)int, 2)
    c <- func(x,y int) int {return x + y}
    println((<-c)(2,3))
}

闭包(closure)

闭包是指在上下文中引用了自由变量(未绑定到特定对象)的代码块(函数),或者说是代码块(函数)与和引用环境的组合体。比如:

func intSeq()func()int{
    i := 0
    println(&i)
    return func()int{
        i += 1
        println(&i,i)
        return i
    }   
}
                                                                                                                                                      
func main(){
    nextInt := intSeq()
    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())

    newInt := intSeq()
    fmt.Println(newInt())
}
输出:
0xc42000a320
0xc42000a320 1
1
0xc42000a320 2
2
0xc42000a320 3
3
0xc42007a010
0xc42007a010 1
1

当nextInt函数返回后,通过输出指针,我们可以看出函数在main运行时,依然引用的是原环境变量指针,这种现象称作闭包。所以说,闭包是函数和引用环境变量的组合体。

因为闭包是通过指针引用环境变量,那么就会导致该变量的生命周期

变长,甚至被分配到堆内存。如果多个匿名函数引用同一个环境变量,会让事情变得更加复杂,比如:

func test()[]func(){
    var s []func()
    for i:= 0;i < 3;i++{
        s =  append(s, func(){
            println(&i , i)
        })
    }
    return s
}
func main(){
    funcSlice := test()
    for _ , f := range funcSlice{
        f()
    }
}
输出:
0xc42000a320 3
0xc42000a320 3
0xc42000a320 3

解决方法就是每次用不同的环境变量或参数赋值,比如修改后的test函数:

func test()[]func(){
    var s []func()
    for i:= 0;i < 3;i++{
        x := i
        s =  append(s, func(){
            println(&x , x)
        })
    }
    return s
}

闭包在不用传递参数的情况下就可以读取和修改环境变量,当然我们是要为这种遍历付出代价的,所以日常开发中,在高并发服务

的场景下建议慎用,除非你明确你的需求必须这样做。

时间: 2024-10-28 14:45:22

golang 函数二 (匿名函数和闭包)的相关文章

PHP函数(六)-匿名函数(闭包函数)

匿名函数能够临时创建一个没有名称的函数,常用作回调函数参数的值 <?php $test = function($a){ echo "Hello,".$a; }; $test("world"); ?> 一定要在匿名函数的结尾处加上分号 执行结果 回调函数将匿名函数做参数 <?php function callback($a){ $a(); } callback(function(){ //声明一个匿名函数并传给callback()函数 echo &q

swift 函数.和匿名函数

函数 注意: 没有定义返回类型的函数会返回特殊的值,叫 Void.它其实是一个空的元组(tuple),没有任何元素,可以写成(). 使用元组作为返回参数,返回多个参数 func count(string: String) -> (vowels: Int, consonants: Int, others: Int) { var vowels = 0, consonants = 0, others = 0 for character in string { switch String(charact

Day10:内置函数、匿名函数、递归函数

一.内置函数 1.数学运算类 2.集合类操作 内置函数个别使用示例 1.any 集合中的元素有一个为真的时候为真, 特别的,若为空串返回为False 1 print(any([0,''])) 2 print(any([0,'',1])) 执行结果 1 False 2 True 2.divmod 取商得余数,用于做分页显示功能 1 print(divmod(10,3)) #取商得余数,用于做分页显示 执行结果 1 (3, 1) 3.eval  把字符串中的数据结构给提取出来 1 dic={'nam

python之内置函数与匿名函数

一内置函数 # print(abs(-1)) # print(all([1,2,'a',None])) # print(all([])) #bool值为假的情况:None,空,0,False # # print(any([])) # print(any([' ',None,False])) #True # print(any(['',None,False])) #False # print(any(['',None,False,1])) #True #bin,oct,hex # print(bi

JavaScript之 ------ 函数(一般函数、动态函数、匿名函数)

JavaScript之 ------ 函数(一般函数.动态函数.匿名函数) 函数 一.一般函数 1.格式: function 函数名(形式参数...) { 执行语句: return 返回值: } 函数是多条执行语句的封装体,只有被调用才会被运行. 注意:调用有参数的函数,但没有给其传值,函数一样可以运行,或者调用没有参数的函数,给其传值,该函数也一样运行. 说的简单点:只要写了函数名后面跟了一对小括号,该函数就会运行. 2.函数虽然定义时是声明成两个参数,但调用时却是可以传入任意个 例: ? 1

python——内置函数和匿名函数

内置函数 接下来,我们就一起来看看python里的内置函数.截止到python版本3.6.2,现在python一共为我们提供了68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数.这些函数有些我们已经用过了,有些我们还没用到过,还有一些是被封印了,必须等我们学了新知识才能解开封印的.那今天我们就一起来认识一下python的内置函数.这么多函数,我们该从何学起呢?     Built-in Functions     abs() dict() help() min() setat

python内置函数和匿名函数

内置函数 68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数.     Built-in Functions     abs() dict() help() min() setattr() all() dir() hex() next() slice() any() divmod() id() object() sorted() ascii() enumerate() input() oct() staticmethod() bin() eval() int() open()

python之迭代器生成器和内置函数,匿名函数

今天学习了迭代器生成器以及内置函数和匿名函数,说实话有些懵圈,有些难度了. 一.迭代器和生成器 1.如何从列表.字典中取值的: index索引 for循环 凡是可以使用for循环取值的都是可迭代的 (1)可迭代协议:内部含有__iter__方法的都是可迭代的 (2)迭代器协议:内部含有__iter__方法和__next__方法的都是迭代器 什么是可迭代的:内部含有__iter__方法的都是可迭代的 什么是迭代器:迭代器=iter(可迭代的),自带一个__next__方法 可迭代最大的优势:节省内

python内置函数及匿名函数

locals  本地作用域/局部作用域 会随着位置的改变而改变globals 全局作用域           永远不变 永远是全局 a = 1 b = 2 print(locals()) print(globals()) def func(): c = 3 d = 4 print(locals()) def func2(): l1 = [] d1 = {} print(locals()) #无论在哪里打印 得到的都是全局作用域中的名字 func() func2() # 结果 # {'__name