龙空技术网

爱上开源之golang入门至实战第四章函数(Func)(六)

程序员紫龙之总监日记 278

前言:

现时我们对“func在c语言什么意思”可能比较珍视,我们都需要分析一些“func在c语言什么意思”的相关内容。那么小编同时在网摘上收集了一些对于“func在c语言什么意思””的相关文章,希望小伙伴们能喜欢,大家一起来了解一下吧!

爱上开源之golang入门至实战第四章函数(Func)(六)

4.4.6 匿名函数和闭包

Go语言支持匿名函数,在前面就讲到过,在Go语言里,函数更像是定义的一个函数类型的对象;

在Go语言里,匿名函数更复合这个特性;匿名函数可以在需要使用函数时再定义函数,匿名函数没有函数名只有函数体,这样GO语言的匿名函数作为一种类型被赋值给函数类型的变量,匿名函数也往往以变量方式传递,这与C语言的回调函数比较类似,不同的是,Go语言支持随时在代码里定义匿名函数。 下面来具体介绍一下匿名函数的定义及使用。

匿名函数是指不需要定义函数名的一种函数实现方式,由一个不带函数名的函数声明和函数体组成。

func(参数列表)(返回参数列表){函数体}

下面我们来看看一个匿名函数的简单例子

fn := func(x int) int {    return x * x}fmt.Printf("Result = %d \n", fn(3))==== OUTPUT ====Result = 9 

上面的例子就是一个简单的匿名函数的示例,示例里通过 func(x int) int, 定义了一个参数类型是int,返回值是int的匿名函数;函数体实现了返回参数的平方的结果;然后将匿名函数定义的变量赋值给变量fn; 最后执行fn(3)对函数进行了调用;

匿名函数也被称闭包函数(函数式语言的术语),它们被允许调用定义在其它环境下的变量。闭包可使得某个函数捕捉到一些外部状态,

例如:函数被创建时的状态。另一种表示方式为:一个闭包继承了 函数所声明时的作用域。这种状态(作用域内的变量)都被共享倒闭包的环境中,因此这些变量可以在闭包中被操作,直到被销毁。闭包经常被用作包装函数:它们会预先定义好 1 个或多个参数以用于包装。另一个不错的应用就是使用闭包来完成更加简洁的错误检查。 仅仅从形式上将闭包简单理解为匿名函数是不够的,还需要理解闭包实质上的含义。看看下面的示例:

func TestAnonymous2(t *testing.T) {   for idx := 0; idx < 10; idx++ {      fn := func() int {         return idx * idx      }      fmt.Printf("Result(%d*%d) = %d \n", idx, idx, fn())   }}==== OUTPUT ====Result(0*0) = 0 Result(1*1) = 1 Result(2*2) = 4 Result(3*3) = 9 Result(4*4) = 16 Result(5*5) = 25 Result(6*6) = 36 Result(7*7) = 49 Result(8*8) = 64 Result(9*9) = 81 

上面的例子,匿名函数就是用了作用域内的变量idx; 对于闭包函数捕获的常量和变量,无论闭包何时何处被调用,闭包都可以使用这些常量和变量,而不用关心它们表面上的作用域。

把上面的例子,改一改,看看匿名函数对作用域的变量idx的修改会有什么样的影响

func TestAnonymous2(t *testing.T) {    for idx := 0; idx < 10; {        fn := func() (rtn int) {            rtn = idx * idx            idx++            return        }        fmt.Printf("Result(%d*%d) = %d \n", idx, idx, fn())    }}==== OUTPUT ====Result(1*1) = 0 Result(2*2) = 1 Result(3*3) = 4 Result(4*4) = 9 Result(5*5) = 16 Result(6*6) = 25 Result(7*7) = 36 Result(8*8) = 49 Result(9*9) = 64 Result(10*10) = 81 

由这段代码以判断出,闭包获取捕获变量相当于直接引用了变量, 对变量的任何修改都可以直接修改变量;类似于引用传递的效果,而非值传递。

func TestAnonymous3(t *testing.T) {    var fn func(x uint8) []uint8    fn = func(x uint8) (rtn []uint8) {        if x == 0 {            rtn = append(rtn, 0)            return        }        if x == 1 {            rtn = append(rtn, 0, 1)            return        }        if x == 2 {            rtn = append(rtn, 0, 1, 1)            return        }        rtn = append(fn(x - 1))        rtn = append(rtn, rtn[len(rtn)-1]+rtn[len(rtn)-2])        return    }    fmt.Printf("Result(%d) = %v \n", 10, fn(10))}==== OUTPUT ====Result(10) = [0 1 1 2 3 5 8 13 21 34 55] 

匿名函数的递归调用的例子; 结合着上面两个例子的有关作用域的特性, 可以写出非常强大的代码。

实质上看,闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。闭包在运行时 可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。由闭包的实质含义,可以判断出,闭包获取捕获变量相当于引用传递,而非值传递;对于闭包函数捕获的常量和变量,无论闭包何时何处被调用,闭包都可以使用这些常量和变量,而不用关心它们表面上的作用域。利用匿名函数(闭包函数)的这些作用域特性去实现一些功能,就是编程技巧的一种体现。

标签: #func在c语言什么意思