zoukankan      html  css  js  c++  java
  • go:匿名函数与闭包

    一、匿名函数

      定义:没有函数名的函数。

      作用:在go语言中目前了解的作用就是用于构成闭包。

      *注:由于javascript不存在块级作用域,故匿名函数常用来包含代码以不污染全局命名空间,运行后销毁环境。

        ----来自知乎回答:http://www.zhihu.com/question/34649602

      使用方法及其原理请参考:http://www.cnblogs.com/chenxianbin89/archive/2010/01/28/1658392.html

      使用举例

      (1)

    a := func() {
    	fmt.Println(1)
    }
    a() //输出:1

      (2)带参数

    b := func(arg int) {
    	fmt.Println(arg)
    }
    b(2) //输出:2
    
    
    (func(arg int) {
    	fmt.Println(arg)
    })(3) //输出:3
    

      (3)带返回值

    c := func() int {
    	fmt.Println(4)
    	return 5
    }
    d := c() //打印输出4,并将5赋值给d
    fmt.Println(d)
    

      

    二、闭包(closure)

      

      闭包的理解参考:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html 

      闭包的用途参考:http://blog.csdn.net/sunlylorn/article/details/6534610

            和   http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html

      简单来说:

      因为把返回的函数赋给了一个变量,虽然函数在执行完一瞬间会销毁其执行环境,

      但是如果有闭包的话,闭包会保存外部函数的活动对象(变量),所以如果不把对闭包的引用消除掉,

      闭包会一直存在内存中,垃圾收集器不会销毁闭包占用的内存。

        ----来自知乎回答http://www.zhihu.com/question/34649602

      使用举例

      (1)

    //函数A是一个不带参数,返回值是一个匿名函数,且该函数
    //带有一个int类型参数,返回值为一个int类型
    func A() func(aa int) int {
    	sum := 0
    	return func(cc int) int {
    		sum += cc
    		fmt.Println("aa=", aa, "bb=", bb, "	sum=", sum)
    		return sum
    	}
    }//编译错误,提示aa未定义

      实际上func(aa int) int只是函数A的返回值,在这里给参数取名无任何作用,反而会影响代码阅读,直接用func(int) int 即可。

      更正后:

    func A() func(int) int {
    	sum := 0
    	return func(bb int) int {
    		sum += bb
    		fmt.Println("bb=", bb, "\tsum=", sum)
    		return sum
    	}
    }
    

      调用1:

    func main() {
    	a := A()//定义变量a,并将函数A的返回值赋给a
    	b := a(4)
    	fmt.Println(b)
    }
    /*
    **    输出:   
    **    bb= 4   sum= 4
    **    4
    */
    

      调用2:

    func main() {
    	a := A()
    	a(0)
    	a(1)
    	a(5)
    }
    /*
    **  输出:
    **  bb= 0 	sum= 0
    **  bb= 1 	sum= 1
    **  bb= 5 	sum= 6
    */
    

      以上调用通过闭包实现了sum的累加

      调用3:

    func main() {
    	a := A()
    	c := A()
    	a(0)
    	a(5)
    	c(10)
    	c(20)
    }
    /*
    **  输出:
    **  bb= 0 	sum= 0
    **  bb= 5 	sum= 5
    **  bb= 10 	sum= 10
    **  bb= 20 	sum= 30   
    */
    

      可以看出,上例中调用了两次函数A,构成了两个闭包,这两个闭包维护的变量sum不是同一个变量。

      (2)

    func B() []func() {
    	b := make([]func(), 3, 3)
    	for i := 0; i < 3; i++ {
    		b[i] = func() {
    			fmt.Println(i)
    		}
    	}
    	return b
    }
    
    func main() {
    	c := B()
    	c[0]()
    	c[1]()
    	c[2]()
    }
    /*
    **  输出:
    **  3
    **  3
    **  3
    */
    

      闭包通过引用的方式使用外部函数的变量。

      上例中只调用了一次函数B,构成一个闭包,i 在外部函数B中定义,所以闭包维护该变量 i ,c[0]、c[1]、c[2]中的 i 都是闭包中 i 的引用。

      因此执行c:=B()后,i 的值已经变为3,故再调用c[0]()时的输出是3而不是0。

     

      可作如下修改:

    func B() []func() {
    	b := make([]func(), 3, 3)
    	for i := 0; i < 3; i++ {
    		b[i] = (func(j int) func() {
    			return func() {
    				fmt.Println(j)
    			}
    		})(i)
    	}
    	return b
    }
    
    func main() {
    	c := B()
    	c[0]()
    	c[1]()
    	c[2]()
    }
    /*
    **    输出:
    **        0
    **        1
    **        2
    */
    

      以上修改可能没有什么实际意义,此处仅为说明问题使用。

      在使用defer的时候可能出现类似问题,需要注意:

    for j := 0; j < 2; j++ {
    	defer (func() {
    		fmt.Println(j)
    	})()
    }
    /*
    **    输出:    
    **    2    
    **    2
    */
    

      

      

      

      

      

  • 相关阅读:
    DEDECMS里面DEDE函数解析
    dede数据库类使用方法 $dsql
    DEDE数据库语句 DEDESQL命令批量替换 SQL执行语句
    织梦DedeCms网站更换域名后文章图片路径批量修改
    DSP using MATLAB 示例 Example3.12
    DSP using MATLAB 示例 Example3.11
    DSP using MATLAB 示例 Example3.10
    DSP using MATLAB 示例Example3.9
    DSP using MATLAB 示例Example3.8
    DSP using MATLAB 示例Example3.7
  • 原文地址:https://www.cnblogs.com/xiaopipi/p/4900587.html
Copyright © 2011-2022 走看看