闭包基本介绍

闭包就是 一个函数 和其相关的 引用环境 组合的一个整体

好处: 保存引用的变量,下次继续使用,不会销毁

下面通过闭包的方式,写一个数字累加器,体验一下闭包的妙处

闭包实现数字累加

package main

import "fmt"

// 累加器
// 闭包 - 函数柯里化
// 返回值类型: func(int) int
func AddUpper() func(int) int {
var n int = 100
return func(i int) int {
n = n + i
return n
}
} func main() {
f := AddUpper()
fmt.Println(f(1)) // 101
fmt.Println(f(2)) // 103
fmt.Println(f(3)) // 106
}

代码说明

  1. AddUpper是一个函数,返回的数据类型 func(int) int

  2. 闭包的说明

返回的是一个匿名函数,但是这个匿名函数引用到了函数外的变量 n ,因此这个匿名函数就和 n 形成一个整体,构成闭包

  1. 当反复调用 f 函数时,因为 n 只初始化一次,保存了变量的值,因此每调用一次就相当于进行了累加。

  2. 我们要搞清楚闭包,关键就是要分析返回的函数使用到哪些变量

代码分析

这里我引入了一个字符串变量str,来帮助分析闭包是怎么保存变量的。

package main

import (
"fmt"
) // 累加器
// 闭包 - 函数柯里化
// 返回值类型: func(int) int
func AddUpper() func(int) int {
var n int = 100
var str = "hello"
return func(i int) int {
n = n + i
fmt.Println("i=", i)
str += string(36) // ascii 36 = '$'
fmt.Printf("str==%s\n", str)
return n
}
} func main() {
f := AddUpper()
// fmt.Println(AddUpper()(1)) // 101
fmt.Println("f(1)=", f(1)) // 101
fmt.Println("f(2)=", f(2)) // 103
fmt.Println("f(3)=", f(3)) // 106
} i= 1
str==hello$
f(1)= 101
i= 2
str==hello$$
f(2)= 103
i= 3
str==hello$$$
f(3)= 106

从输出可以看出来,闭包引用的变量nstr并没有在调用函数的时候重复声明,而是保留了下次函数调用后更新的值。

闭包案例

需求:

  1. 编写一个函数 makeSuffix(suffix string) ,可以接收一个文件后缀名,并返回一个闭包

  2. 调用闭包,可以传入一个文件名,如果该文件名没有指定后缀,则返回 文件名.jpg ,如果已经有.jpg,则返回原文件名。

strings.HasSuffix,该函数可以判断某个字符串是否有指定的后缀。

上代码

package main

import (
"fmt"
"strings"
) func makeSuffix(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
} // 传统写法
func makeSuffixV2(suffix string, name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
} func main() {
// 闭包调用
f := makeSuffix(".jpg")
fmt.Println(f("xiao")) // xiao.jpg
fmt.Println(f("xiaoxiao.jpg")) // xiaoxiao.jpg
fmt.Println(f("xiaoxiao.666")) // xiaoxiao.666.jpg // 传统写法调用
fmt.Println("makeSuffixV2=", makeSuffixV2(".jpg", "allblue")) // makeSuffixV2= allblue.jpg
fmt.Println("makeSuffixV2=", makeSuffixV2(".jpg", "all.blue")) // makeSuffixV2= all.blue.jpg
}

代码说明

返回的匿名函数和 makeSuffix(suffix string) 的 suffix 变量组合成一个闭包

传统写法和闭包写法实现效果一样,但是,传统写法需要重复写变量, 比如上面的

makeSuffixV2(".jpg", "all.blue"))

闭包则解决了这个问题,是代码看起来更加的简洁

闭包的好处之一: 参数复用

好处: 保存引用的变量,下次继续使用,不会销毁

函数柯里化(闭包)

参考我的另一篇文章: 甜点cc的语雀知识库

我是 甜点cc

微信公众号:【看见另一种可能】

专注前端开发,也喜欢专研各种跟本职工作关系不大的技术,技术、产品兴趣广泛且浓厚。本号主要致力于分享个人经验总结,希望可以给一小部分人一些微小帮助。

Go | 闭包的使用的更多相关文章

  1. 《Web 前端面试指南》1、JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

  2. 干货分享:让你分分钟学会 JS 闭包

    闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...

  3. 深入浅出JavaScript之闭包(Closure)

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  4. javascript之闭包理解以及应用场景

    半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...

  5. js闭包 和 prototype

    function test(){ var p=200; function q(){ return p++; } return q; } var s = test(); alert(s()); aler ...

  6. js闭包for循环总是只执行最后一个值得解决方法

    <style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...

  7. JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象

    一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...

  8. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  9. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  10. JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

随机推荐

  1. Kubernetes 日志:搭建 EFK 日志系统

    Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch.Fluentd 和 Kibana(EFK)技术栈,也是官方现在比较推荐的一种方案. Elasticsearch 是一个 ...

  2. ProxySQL Cluster 概述

    文章转载自:https://blog.csdn.net/n88Lpo/article/details/79608639 前言 在ProxySQL 1.4.2 之前,ProxySQL 单点的解决方法有配 ...

  3. ProxySQL(7):详述ProxySQL的路由规则

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9300829.html 关于ProxySQL路由的简述 当ProxySQL收到前端app发送的SQL语句后,它 ...

  4. cAdvisor容器监控规则

    其他说明参考host主机监控规则:https://www.cnblogs.com/sanduzxcvbnm/p/13589848.html 在prometheus主程序目录下的rules目录下新建do ...

  5. GitLab 之 PlantUML 的配置及使用

    转载自:https://cloud.tencent.com/developer/article/1010617 1.PlantUML介绍 UML 统一建模语言是一个通用的可视化建模语言,用于对软件进行 ...

  6. 在图片不被裁剪时opencv绕图片中任意点旋转任意角度

    opencv绕图片中任意角度旋转任意角度   最近在做项目需要把把图片绕图片中任意点旋转任意角度,考虑到自己旋转需要编写插值算法,所以想到了用opencv,但是网上都是围绕图片中点旋转任意角度的,都是 ...

  7. C#-13 泛型

    一 泛型 泛型提供了一种更优雅的方式,可以让多个类型共享一组代码.泛型允许我们声明类型参数化的代码,可以用不同的类型进行实例化. 也就是说,我们可以用"类型占位符"来写代码,然后在 ...

  8. Petrozavodsk Winter Training Camp 2016: Moscow SU Trinity Contest

    题目列表 A.ABBA E.Elvis Presley G. Biological Software Utilities J. Burnished Security Updates A.ABBA 题意 ...

  9. 插件化编程之WebAPI统一返回模型

    WebApi返回数据我们一般包裹在一个公共的模型下面的,而不是直接返回最终数据,在返回参数中,显示出当前请求的时间戳,是否请求成功,如果错误那么错误的消息是什么,状态码(根据业务定义的值)等等.我们常 ...

  10. Linux 下配置 hosts 并设置免密登录

    Linux 下配置 hosts 并设置免密登录 作者:Grey 原文地址: 博客园:Linux 下配置 hosts 并设置免密登录 CSDN:Linux 下配置 hosts 并设置免密登录 说明 实现 ...