首页 > 其他分享 >Go中的闭包、递归

Go中的闭包、递归

时间:2022-10-09 16:55:26浏览次数:32  
标签:闭包 return 递归 int fmt func Go main

一 闭包详解

闭包的应该都听过,但到底什么是闭包呢?

闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。

“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

维基百科讲,闭包(Closure),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

看着上面的描述,会发现闭包和匿名函数似乎有些像。可是可能还是有些云里雾里的。因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。目前在JavaScript、Go、PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、Ruby、 Python、Lua、objective c、Swift 以及Java8以上等语言中都能找到对闭包不同程度的支持。通过支持闭包的语法可以发现一个特点,他们都有垃圾回收(GC)机制。

在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。变量的作用域仅限于包含它们的函数,因此无法从其它程序代码部分进行访问。不过,变量的生存期是可以很长,在一次函数调用期间所创建所生成的值在下次函数调用时仍然存在。正因为这一特点,闭包可以用来完成信息隐藏,并进而应用于需要状态表达的某些编程范型中。

二 Go的闭包

Go语言是支持闭包的,这里只是简单地讲一下在Go语言中闭包是如何实现的。 下面我来将闭包例子用Go来实现。

package main

import (
    "fmt"
)

func a() func() int {
    i := 0
    b := func() int {
        i++
        fmt.Println(i)
        return i
    }
    return b
}

func main() {
    c := a()
    c()
    c()
    c()

    a() //不会输出i
}

输出结果:

    1
    2
    3

可以发现,输出和之前的JavaScript的代码是一致的。具体的原因和上面的也是一样的,这说明Go语言是支持闭包的。

闭包复制的是原对象指针,这就很容易解释延迟引用现象。

package main

import "fmt"

func test() func() {
    x := 100
    fmt.Printf("x (%p) = %d\n", &x, x)

    return func() {
        fmt.Printf("x (%p) = %d\n", &x, x)
    }
}

func main() {
    f := test()
    f()
}

输出:

    x (0xc42007c008) = 100
    x (0xc42007c008) = 100

在汇编层 ,test 实际返回的是 FuncVal 对象,其中包含了匿名函数地址、闭包对象指针。当调 匿名函数时,只需以某个寄存器传递该对象即可。

    FuncVal { func_address, closure_var_pointer ... }

外部引用函数参数局部变量

package main

import "fmt"

// 外部引用函数参数局部变量
func add(base int) func(int) int {
    return func(i int) int {
        base += i
        return base
    }
}

func main() {
    tmp1 := add(10)
    fmt.Println(tmp1(1), tmp1(2))
    // 此时tmp1和tmp2不是一个实体了
    tmp2 := add(100)
    fmt.Println(tmp2(1), tmp2(2))
}

返回2个闭包

package main

import "fmt"

// 返回2个函数类型的返回值
func test01(base int) (func(int) int, func(int) int) {
    // 定义2个函数,并返回
    // 相加
    add := func(i int) int {
        base += i
        return base
    }
    // 相减
    sub := func(i int) int {
        base -= i
        return base
    }
    // 返回
    return add, sub
}

func main() {
    f1, f2 := test01(10)
    // base一直是没有消
    fmt.Println(f1(1), f2(2))
    // 此时base是9
    fmt.Println(f1(3), f2(4))
}

三 Go 语言递归函数

递归,就是在运行的过程中调用自己。 一个函数调用自己,就叫做递归函数。

构成递归需具备的条件:

    1.子问题须与原始问题为同样的事,且更为简单。
    2.不能无限制地调用本身,须有个出口,化简为非递归状况处理。

数字阶乘

一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。

package main

import "fmt"

func factorial(i int) int {
    if i <= 1 {
        return 1
    }
    return i * factorial(i-1)
}

func main() {
    var i int = 7
    fmt.Printf("Factorial of %d is %d\n", i, factorial(i))
}

输出结果:

    Factorial of 7 is 5040

斐波那契数列(Fibonacci)

这个数列从第3项开始,每一项都等于前两项之和。

package main

import "fmt"

func fibonaci(i int) int {
    if i == 0 {
        return 0
    }
    if i == 1 {
        return 1
    }
    return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    var i int
    for i = 0; i < 10; i++ {
        fmt.Printf("%d\n", fibonaci(i))
    }
}

输出结果:

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34

标签:闭包,return,递归,int,fmt,func,Go,main
From: https://www.cnblogs.com/qi66/p/16772750.html

相关文章

  • 【Java复健指南03】递归思想
    【递归】递归重要规则1.执行一个方法时,就创建一个新的受保护的独立空间(栈空间)方法的局部变量是独立的,不会相互影响,比如n变量如果方法中使用的是引用类型变量(比......
  • python递归算法
    递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是“自己调自己”,一个使用递归技术的方法将会直接或间接的调用自己。利用递归可以用简单的程序来解决......
  • mongo常用
    默认端口 介绍27017 mongod和mongos实例的默认端口,你可以通过port或--port改变该端口27018 设置--shardsvr运行变量或在配置文件里设置clusterRole为shards......
  • CentOS 7.9 安装 django-3.2.10
    一、CentOS7.9安装django-3.2.10地址https://www.djangoproject.comhttps://github.com/django/django二、安装django先得安装pythonpython3python3-Vpip3-......
  • Google 发布:DevOps 2022现状报告
    在过去的八年中,全球超过33,000名专业人士参与了AccelerateStateofDevOps调查,使其成为同类研究中规模最大、运行时间最长的一项。AccelerateStateofDevOps报告提......
  • fibnacci数列递归实现
    fibnacci数列递归实现1.什么是斐波那契(fibnacci)数列?斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...这个数列从第3项开始,每一项都等于前两项之和。2.递归表达式F(......
  • Go中select条件语句详解
    一select语句select语句类似于switch语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。select是Go中的一个控制结构,类似......
  • Google 测试总监聊如何经营成功的测试职业生涯
    你是如何开始做测试工作的?1989年,我在田纳西大学读研究生的时候,完成了从软件开发人员到软件测试人员的转型。而这一转型并非出于我自己的选择。我命运的改变发生在一个早......
  • 基于Gossip的online server
    在游戏服务端架构中onlineserver,有些也叫centerserver。主要承载以下功能:存储玩家的在线信息,处理上线和下线消息。转发消息给特定玩家。onlineserver在架构图中......
  • MongoDB安装
    首先,我们去官网看看,MongoDB下载。  先把安装包下载下来,然后就是正常安装软件的步骤:双击打开,next=> 打上勾,继续next=>   选Custom  Browser选择安装路......