举例讲解Go语言中函数的闭包使用

和变量的声明不同,Go语言不能在函数里声明另外一个函数。所以在Go的源文件里,函数声明都是出现在最外层的。

“声明”就是把一种类型的变量和一个名字联系起来。

Go里有函数类型的变量,这样,虽然不能在一个函数里直接声明另一个函数,但是可以在一个函数中声明一个函数类型的变量,此时的函数称为闭包(closure)。

例:

代码如下:

packagemain
 
import"fmt"
 
funcmain(){
    add:=func(baseint)func(int)(int){
        returnfunc(iint)(int){
            returnbase+i
        }
    }
   
    add5:=add(5)
    fmt.Println("add5(10)=",add5(10))
}

这个例子唯一的使用价值大概就是用来展示闭包的构建和使用。

add是一个闭包,因为它是无名的函数类型的变量。可以认为它是一个闭包作坊,根据入参返回(生产)一个闭包。这样add5就是使用5作为add的参数得到的一个闭包。

闭包的声明是在另一个函数的内部,形成嵌套。和块的嵌套一样,内层的变量可以遮盖同名的外层的变量,而且外层变量可以直接在内层使用。如add的base参数在return返回的闭包的外层,所以它的值5在add返回并赋值给add5后依旧存在。当add5执行时,参数i可以从这个外层得到的base相加,得到结果15.

个人理解:

其实理解闭包的最方便的方法就是将闭包函数看成一个类,一个闭包函数调用就是实例化一个类。

然后就可以根据类的角度看出哪些是“全局变量”,哪些是“局部变量”了。

比如上例中的adder函数返回func(int) int 的函数

pos和neg分别实例化了两个“闭包类”,在这个“闭包类”中有个“闭包全局变量”sum。所以这样就很好理解返回的结果了。

再来看下面一个例子:

代码如下:

package main

import "fmt"

func adder() func(int) int {
     sum := 0
     return func(x int) int {
          sum += x
          return sum
     }
}

func main() {
     pos, neg := adder(), adder()
     for i := 0; i < 10; i++ {
          fmt.Println(
               pos(i),
               neg(-2*i),
          )
     }
}

运行返回结果:

0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

这个就是Go中的闭包,一个函数和与其相关的引用环境组合而成的实体。

(0)

相关推荐

  • 深入分析golang多值返回以及闭包的实现

    一.前言 golang有很多新颖的特性,不知道大家的使用的时候,有没想过,这些特性是如何实现的?当然你可能会说,不了解这些特性好像也不影响自己使用golang,你说的也有道理,但是,多了解底层的实现原理,对于在使用golang时的眼界是完全不一样的,就类似于看过http的实现之后,再来使用http框架,和未看过http框架时的眼界是不一样的,当然,你如果是一名it爱好者,求知欲自然会引导你去学习. 二.这篇文章主要就分析两点:      1.golang多值返回的实现;      2.golan

  • 简单了解Go语言中函数作为值以及函数闭包的使用

    函数作为值 Go编程语言提供灵活性,以动态创建函数,并使用它们的值.在下面的例子中,我们已经与初始化函数定义的变量.此函数变量的目仅仅是为使用内置的Math.sqrt()函数.下面是一个例子: 复制代码 代码如下: package main import (    "fmt"    "math" ) func main(){    /* declare a function variable */    getSquareRoot := func(x float64

  • 深入理解Go语言中的闭包

    闭包 在函数编程中经常用到闭包,闭包是什?它是怎么产生的及用来解决什么问题呢?先给出闭包的字面定义:闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境).这个从字面上很难理解,特别对于一直使用命令式语言进行编程的程序员们. Go语言中的闭包 先看一个demo: func f(i int) func() int { return func() int { i++ return i } } 函数f返回了一个函数,返回的这个函数就是一个闭包.这个函数中本身是没有定义变量i的,而是引用

  • JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染

    如代码块 复制代码 代码如下: if (true) { int i = 100; } print(i); //错误,变量i没有声明 如上面例子所示,代码块外的函数是无法访问i变量的. 但在javaScript里,情况则完全不同. 复制代码 代码如下: if (true) { var i = 100; } alert(i); //弹出框并显示100 很多现代语言都推荐尽可能迟地声明变量,但在Javascript里这是一个最糟糕的建议.由于缺少块级作用域,最好在函数体的顶部声明函数中可能用到的所有变

  • 举例讲解Go语言中函数的闭包使用

    和变量的声明不同,Go语言不能在函数里声明另外一个函数.所以在Go的源文件里,函数声明都是出现在最外层的. "声明"就是把一种类型的变量和一个名字联系起来. Go里有函数类型的变量,这样,虽然不能在一个函数里直接声明另一个函数,但是可以在一个函数中声明一个函数类型的变量,此时的函数称为闭包(closure). 例: 复制代码 代码如下: packagemain   import"fmt"   funcmain(){     add:=func(baseint)fun

  • 深入讲解Go语言中函数new与make的使用和区别

    前言 本文主要给大家介绍了Go语言中函数new与make的使用和区别,关于Go语言中new和make是内建的两个函数,主要用来创建分配类型内存.在我们定义生成变量的时候,可能会觉得有点迷惑,其实他们的规则很简单,下面我们就通过一些示例说明他们的区别和使用,话不多说了,来一起看看详细的介绍吧. 变量的声明 var i int var s string 变量的声明我们可以通过var关键字,然后就可以在程序中使用.当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如int类型的零值是0,st

  • 深入了解Rust中函数与闭包的使用

    目录 闭包 高阶函数 发散函数 闭包 Rust 的闭包由一个匿名函数加上外层的作用域组成,举个例子: fn main() {     let closure = |n: u32| -> u32 {         n * 2     };     println!("n * 2 = {}", closure(12));     // n * 2 = 24 } 闭包可以被保存在一个变量中,然后我们注意一下它的语法,参数定义.返回值定义都和普通函数一样,但闭包使用的是两个竖线.我们对

  • 一文带你熟悉Go语言中函数的使用

    目录 函数 函数的声明 Go 函数支持变长参数 匿名函数 闭包 init 函数 函数参数详解 形式参数与实际参数 值传递 函数是一种数据类型 小结 函数 函数的英文单词是 Function,这个单词还有着功能的意思.在 Go 语言中,函数是实现某一特定功能的代码块.函数代表着某个功能,可以在同一个地方多次使用,也可以在不同地方使用.因此使用函数,可以提高代码的复用性,减少代码的冗余. 函数的声明 通过案例了解函数的声明有哪几部分: 定义一个函数,实现两个数相加的功能,并将相加之后的结果返回. f

  • C语言中函数栈帧的创建和销毁的深层分析

    目录 一.本文目标 二.基础知识 1.寄存器 2.代码案例 3.总体栈帧概况 4.所需反汇编代码总览 三.函数栈帧创建销毁过程 1._tmainCRTStartup函数(调用main函数)栈帧的创建 2.main函数栈帧的创建 3.main函数内执行有效代码(变量) 4.Add函数栈帧的创建 5.Add函数内执行有效代码 6.Add函数栈帧的销毁 7.main函数栈帧的销毁 四.总结 一.本文目标 1.局部变量是怎么创建的? 2.为什么局部变量的值是随机值? 3.函数是怎么传参的?传参的顺序是怎

  • C语言中函数指针的三种使用方法总结

     C语言中函数指针的三种使用方法总结 在这里分享一下自己的心得,希望和大家一起分享技术,如果有什么不足,还请大家指正.写出这篇目的,就是希望大家一起成长,我也相信技术之间没有高低,只有互补,只有分享,才能使彼此更加成长. 定义方式:int (*p)(int x, int y); 实现代码: #include <stdio.h> int sum(int x, int y){ return x + y; } int reduce(int x, int y){ return x - y; } int

  • C语言中函数与指针的应用总结

    1. 首先,在C语言中函数是一种function-to-pointer的方式,即对于一个函数,会将其自动转换成指针的类型. 复制代码 代码如下: #include<stdio.h> void fun(){} int main(void){   printf("%p %p %p\n", &fun, fun, *fun);   return 0;} -------------------------------------------------------------

  • C语言中函数参数的入栈顺序详解及实例

    C语言中函数参数的入栈顺序详解及实例 对技术执着的人,比如说我,往往对一些问题,不仅想做到"知其然",还想做到"知其所以然".C语言可谓博大精深,即使我已经有多年的开发经验,可还是有许多问题不知其所以然.某天某地某人问我,C语言中函数参数的入栈顺序如何?从右至左,我随口回答.为什么是从右至左呢?我终究没有给出合理的解释.于是,只好做了个作业,于是有了这篇小博文. #include void foo(int x, int y, int z) { printf(&quo

  • 漫画讲解C语言中最近公共祖先的三种类型

    最近公共祖先定义 查找最近公共祖先 三叉链 代码如下: //三叉链 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode *parent; TreeNode(int x) : val(x), left(NULL), right(NULL), parent(NULL) {} }; class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* ro

  • go语言中函数与方法介绍

    在C#或者Java里面我们都知道,一个Class是要包含成员变量和方法的,对于GO语言的Struct也一样,我们也可以给Struct定义一系列方法. 一.怎么定义一个方法? Go的方法是在函数前面加上一个接收者,这样编译器就知道这个方法属于哪个类型了.例如: package demo1 import ( "fmt" ) type Student struct { Name string Age int Class string } func (stu Student) GetUserI

随机推荐