Go | 闭包的使用
闭包基本介绍
闭包就是 一个函数 和其相关的 引用环境 组合的一个整体
好处: 保存引用的变量,下次继续使用,不会销毁
下面通过闭包的方式,写一个数字累加器,体验一下闭包的妙处
闭包实现数字累加
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
}
代码说明
AddUpper是一个函数,返回的数据类型 func(int) int
闭包的说明

返回的是一个匿名函数,但是这个匿名函数引用到了函数外的变量 n ,因此这个匿名函数就和 n 形成一个整体,构成闭包
当反复调用
f函数时,因为 n 只初始化一次,保存了变量的值,因此每调用一次就相当于进行了累加。我们要搞清楚闭包,关键就是要分析返回的函数使用到哪些变量
代码分析
这里我引入了一个字符串变量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
从输出可以看出来,闭包引用的变量n和str并没有在调用函数的时候重复声明,而是保留了下次函数调用后更新的值。
闭包案例
需求:
编写一个函数 makeSuffix(suffix string) ,可以接收一个文件后缀名,并返回一个闭包
调用闭包,可以传入一个文件名,如果该文件名没有指定后缀,则返回 文件名.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 | 闭包的使用的更多相关文章
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- 干货分享:让你分分钟学会 JS 闭包
闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...
- 深入浅出JavaScript之闭包(Closure)
闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...
- javascript之闭包理解以及应用场景
半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...
- js闭包 和 prototype
function test(){ var p=200; function q(){ return p++; } return q; } var s = test(); alert(s()); aler ...
- js闭包for循环总是只执行最后一个值得解决方法
<style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...
- JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- 如何设计一门语言(七)——闭包、lambda和interface
人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
- JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
随机推荐
- Kubernetes 中部署 NFS-Subdir-External-Provisioner 为 NFS 提供动态分配卷
文章转载自:http://www.mydlq.club/article/109/ 系统环境: 操作系统: CentOS 7.9 Docker 版本: 19.03.13 Kubernetes 版本: 1 ...
- k8s中的ingress使用上层负载均衡进行设置访问
注意:这种情况下需要有个前提条件,也就是ingress-nginx-controller安装后的service是NodePort或者hostNetwork模式,而不能是ClusterIP,因为负载均衡 ...
- 第一个Django应用 - 第三部分:Django视图和模板
一.概述 一个视图就是一个页面,通常提供特定的功能,使用特定的模板.例如:在一个博客应用中,你可能会看到下列视图: 博客主页:显示最新发布的一些内容 每篇博客的详细页面:博客的永久链接 基于年的博客页 ...
- nsis离开自定义页面保存设置
这是群里一位朋友问他的自定义页面设置完成后返回上一步无法保存怎么办写的一个小例子,拓展了下,只要不关闭,不管上一步还是进入下一步返回都可以保留原页面设置. !include LogicLib.nsh ...
- 文件内再分类到各txt文件
当老师叫我们帮他做事,比如文件内内容再分类,我们就可以建个面板,里面有各要导入文件按钮,先把分类内容copy下,再点按钮导入进txt文件就行啦. 以下为java代码,使用了tableLayout布局 ...
- CentOS6/7开机启动配置
最近在配置Linux系统的ntp校时,涉及到开机启动问题,总结一下 两个环境: CentOS release 6.5 (Final) CentOS Linux release 7.9.2009 (Co ...
- Dubbo 03: 直连式 + 接口工程
进一步改正dubbo框架中简单的直连式的不足 需要用到3个相互独立的maven工程,项目1为maven的java工程作为接口工程,项目2,3为maven的web工程 工程1:o3-link-inter ...
- VS Code For Web 深入浅出 -- 进程间通信篇
在上一篇中,我们一起分析了 VS Code 整体的代码架构,了解了 VS Code 是由前后端分离的方式开发的.且无论前端是基于 electron 还是 web,后端是本地还是云端,其调用方式并无不同 ...
- nordic——nrf52系列SWD设置回读保护
在开发时可能需要回读保护功能,在产品出厂后这个功能可以让你的代码更加安全,无法用SEGGER或者其余方式读取你的代码HEX文件,也就是禁用SWD下载接口.但是SWD锁住了,还想使用(从新下载代码)也是 ...
- JS逆向实战3——AESCBC 模式解密
爬取某省公共资源交易中心 通过抓包数据可知 这个data是我们所需要的数据,但是已经通过加密隐藏起来了 分析 首先这是个json文件,我们可以用请求参数一个一个搜 但是由于我们已经知道了这是个json ...