当前位置:首页 > 科技  > 软件

Go语言中的闭包:封装数据与功能的强大工具

来源: 责编: 时间:2023-11-01 17:04:27 403观看
导读闭包是包括 Go 在内的编程语言的一项强大功能。通过闭包,您可以在函数中封装数据,并通过函数的返回值访问这些数据。在本文中,我们将介绍 Go 中闭包的基础知识,包括它们是什么、如何工作以及如何有效地使用它们。什么是闭

闭包是包括 Go 在内的编程语言的一项强大功能。通过闭包,您可以在函数中封装数据,并通过函数的返回值访问这些数据。在本文中,我们将介绍 Go 中闭包的基础知识,包括它们是什么、如何工作以及如何有效地使用它们。NXL28资讯网——每日最新资讯28at.com

什么是闭包?

go官方有一句解释:NXL28资讯网——每日最新资讯28at.com

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.NXL28资讯网——每日最新资讯28at.com

翻译过来就是:NXL28资讯网——每日最新资讯28at.com

函数字面量(匿名函数)是闭包:它们可以引用在周围函数中定义的变量。然后,这些变量在周围的函数和函数字面量之间共享,只要它们还可以访问,它们就会继续存在。NXL28资讯网——每日最新资讯28at.com

闭包是一种创建函数的方法,这些函数可以访问在其主体之外定义的变量。闭包是一个可以捕捉其周围环境状态的函数。这意味着函数可以访问不在其参数列表中或在其主体中定义的变量。闭包函数可以在外部函数返回后访问这些变量。NXL28资讯网——每日最新资讯28at.com

在 Go 中创建闭包

在 Go 中,您可以使用匿名函数创建闭包。创建闭包时,函数会捕获其周围环境的状态,包括外部函数中定义的任何变量。闭包函数可以在外部函数返回后访问这些变量。NXL28资讯网——每日最新资讯28at.com

下面是一个在 Go 中创建闭包的示例:NXL28资讯网——每日最新资讯28at.com

func adder() func(int) int { // 外部函数 sum := 0 return func(x int) int { // 内部函数  fmt.Println("func sum: ", sum)  sum += x  return sum }}func main() { a := adder() fmt.Println(a(1)) fmt.Println(a(2)) fmt.Println(a(3))}

在本例中,我们定义了一个返回匿名函数的加法器函数。匿名函数捕捉加法器函数中定义的 sum 变量的状态。每次调用匿名函数时,它都会将参数加到求和变量中,并返回结果。NXL28资讯网——每日最新资讯28at.com

所以其输出结果为:NXL28资讯网——每日最新资讯28at.com

func sum:  01func sum:  13func sum:  36

在 Go 中使用闭包

在 Go 中,闭包可用于多种用途,包括用函数封装数据、创建生成器、迭代器和 memoization 函数。NXL28资讯网——每日最新资讯28at.com

下面是一个使用闭包将数据与函数封装在一起的示例:NXL28资讯网——每日最新资讯28at.com

func makeGreeter(greeting string) func(string) string { return func(name string) string {  fmt.Printf("func greeting: %s, name: %s/n", greeting, name)  return greeting + ", " + name }}func main() { englishGreeter := makeGreeter("Hello") spanishGreeter := makeGreeter("Hola") fmt.Println(englishGreeter("John")) fmt.Println(englishGreeter("Tim")) fmt.Println(spanishGreeter("Juan")) fmt.Println(spanishGreeter("Taylor"))}

在本例中,我们定义了一个名为 makeGreeter 的函数,它返回一个匿名函数。该匿名函数接收一个字符串参数,并返回一个将问候语和名称连接起来的字符串。我们创建了两个问候语程序,一个用于英语,一个用于西班牙语,然后用不同的名称调用它们。NXL28资讯网——每日最新资讯28at.com

所以其输出为:NXL28资讯网——每日最新资讯28at.com

func greeting: Hello, name: JohnHello, Johnfunc greeting: Hello, name: TimHello, Timfunc greeting: Hola, name: JuanHola, Juanfunc greeting: Hola, name: TaylorHola, Taylor

替换捕获的变量

Go 闭包的强大功能之一是能够更改捕获的变量。这使得代码中的行为更加灵活和动态。下面是一个例子:NXL28资讯网——每日最新资讯28at.com

func makeCounter() func() int { i := 0 return func() int {  fmt.Println("func i: ", i)  i++  return i }}func main() { counter := makeCounter() fmt.Println(counter()) fmt.Println(counter()) fmt.Println(counter())}

在本例中,makeCounter 函数返回一个闭包,每次调用都会使计数器递增。i 变量被闭包捕获,并可被修改以更新计数器。NXL28资讯网——每日最新资讯28at.com

所以其输出为:NXL28资讯网——每日最新资讯28at.com

func i:  01func i:  12func i:  23

逃逸变量

Go 闭包的另一个高级概念是变量逃逸分析。在 Go 中,变量通常在堆栈上分配,并在超出作用域时被去分配。然而,当变量被闭包捕获时,它必须在堆上分配,以确保在函数返回后可以访问它。这会导致性能开销,因此了解变量何时以及如何逃逸非常重要。NXL28资讯网——每日最新资讯28at.com

我们对比一下两个方法:NXL28资讯网——每日最新资讯28at.com

func makeAdder1(x1 int) func(int) int { return func(y1 int) int {  return x1 + y1 }}func makeAdder2(x2 int) func(int) int { fmt.Println(x2) return func(y2 int) int {  return x2 + y2 }}func main() { a := makeAdder1(5) fmt.Println(a(1)) b := makeAdder2(6) fmt.Println(b(1))}

makeAdder1 和 makeAdder2 的区别在于函数内的 x 是否被使用。NXL28资讯网——每日最新资讯28at.com

而我们通过逃逸分析:NXL28资讯网——每日最新资讯28at.com

go build -gcflags "-m" main.go

会得到以下输出:NXL28资讯网——每日最新资讯28at.com

./main.go:5:6: can inline makeAdder1./main.go:6:9: can inline makeAdder1.func1./main.go:13:9: can inline makeAdder2.func1./main.go:12:13: inlining call to fmt.Println./main.go:19:17: inlining call to makeAdder1./main.go:6:9: can inline main.makeAdder1.func1./main.go:20:15: inlining call to main.makeAdder1.func1./main.go:20:13: inlining call to fmt.Println./main.go:23:13: inlining call to fmt.Println./main.go:6:9: func literal escapes to heap./main.go:12:13: ... argument does not escape./main.go:12:14: x2 escapes to heap./main.go:13:9: func literal escapes to heap./main.go:19:17: func literal does not escape./main.go:20:13: ... argument does not escape./main.go:20:15: ~R0 escapes to heap./main.go:23:13: ... argument does not escape./main.go:23:15: b(1) escapes to heap

从逃逸分析结果来看,x 变量被闭包捕获,必须在堆上分配。不过,如果 x 变量不被闭包之外的任何其他代码使用,编译器可以进行优化,将其分配到栈中。NXL28资讯网——每日最新资讯28at.com

共享闭包

最后,Go 中的闭包可以在多个函数之间共享,从而实现更高的灵活性和模块化代码。下面是一个例子:NXL28资讯网——每日最新资讯28at.com

type Calculator struct { add func(int, int) int}func NewCalculator() *Calculator { c := &Calculator{} c.add = func(x, y int) int {  fmt.Printf("func x: %d, y: %d/n", x, y)  return x + y } return c}func (c *Calculator) Add(x, y int) int { return c.add(x, y)}func main() { calc := NewCalculator() fmt.Println(calc.Add(1, 2)) fmt.Println(calc.Add(2, 3))}

在本例中,Calculator 结构具有一个 add 函数,该函数在 NewCalculator 函数中通过闭包进行了初始化。Calculator 结构的 Add 方法只需调用 add 函数,这样就可以在多个上下文中重复使用。NXL28资讯网——每日最新资讯28at.com

所以其输出为:NXL28资讯网——每日最新资讯28at.com

func x: 1, y: 23func x: 2, y: 35

结论

在 Go 编程中,闭包是一个强大的工具,可用于用函数封装数据,并创建生成器和迭代器等。它们提供了一种访问函数体外定义的变量的方法,即使在函数返回后也是如此。NXL28资讯网——每日最新资讯28at.com


NXL28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-16368-0.htmlGo语言中的闭包:封装数据与功能的强大工具

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Rust编程基础之六大数据类型

下一篇: 你知道 Python 其实自带了小型数据库吗

标签:
  • 热门焦点
  • Find N3入网:最高支持16+1TB

    OPPO将于近期登场的Find N3折叠屏目前已经正式入网,型号为PHN110。本次Find N3在外观方面相比前两代有很大的变化,不再是小号的横向折叠屏,而是跟别的厂商一样采用了较为常见的
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 如何正确使用:Has和:Nth-Last-Child

    我们可以用CSS检查,以了解一组元素的数量是否小于或等于一个数字。例如,一个拥有三个或更多子项的grid。你可能会想,为什么需要这样做呢?在某些情况下,一个组件或一个布局可能会
  • 年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元“人在职场,应该选择什么样的着装?”近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • iQOO 11S新品发布会

    iQOO将在7月4日19:00举行新品发布会,推出杭州亚运会电竞赛事官方用机iQOO 11S。
  • Counterpoint :OPPO双旗舰战略全面落地 高端产品销量增长22%

    2023年6月30日,全球行业分析机构Counterpoint Research发布的《中国智能手机高端市场白皮书》显示,中国智能手机品牌正在寻求高质量发展,中国高端智能
  • 英特尔Xe-HP项目终止,将专注Xe-HPC/HPG系列显卡

    据10 月 31 日消息报道,英特尔高级副总裁兼加速计算系统和图形事业部总经理 表示,Xe-HP“ Arctic Sound” 系列服务器 GPU 已经应用于 oneAPI devcloud 云服
  • 华为举行春季智慧办公新品发布会 首次推出电子墨水屏平板

    北京时间2月27日晚,华为在巴塞罗那举行春季智慧办公新品发布会,在海外市场推出之前已经在中国市场上市的笔记本、平板、激光打印机等办公产品,并首次推出搭载
  • 苹果MacBook Pro 2021测试:仍不支持平滑滚动

    据10月30日9to5 Mac 消息报道,苹果新的 14 英寸和 16 英寸 MacBook Pro 2021 上市后获得了不错的评价,亮点包括行业领先的性能,令人印象深刻的电池续航,精美丰
Top