【Go】匿名函数与闭包

目录

一、匿名函数

基础介绍

形式

示例程序 1: 直接调用

示例程序 2: 作为变量赋值

示例程序 3: 作为函数参数

示例程序 4: 使用匿名函数进行排序

示例程序 5: 匿名函数用于延迟执行

示例程序 6: 通过匿名函数实现迭代器

二、闭包用法

基础知识

示例程序 1: 状态保持器

示例程序 2: 生成器函数

示例程序 3: 事件处理

示例程序 4: 资源清理


一、匿名函数

        在Go语言中,匿名函数是没有名字的函数,可以在需要的地方直接定义和使用。匿名函数的一个重要用途是实现闭包。在Go中,匿名函数可以被赋值给变量,作为参数传递,或直接在其它函数内调用。这提供了极大的灵活性和代码的简洁性。下面,我将介绍匿名函数的基本概念,并提供三个示例程序来展示其使用方法。

基础介绍

形式

        匿名函数通常定义的形式是:

func(参数列表) 返回类型 {// 函数体
}

        可以将其赋值给一个变量,或者直接在需要的地方调用。

示例程序 1: 直接调用

        这个示例展示了如何直接调用一个匿名函数,无需先赋值给变量。

package mainimport "fmt"func main() {// 直接定义并调用匿名函数func(msg string) {fmt.Println(msg)}("Hello, Go!")
}

        在这个例子中,匿名函数被直接调用,并传递了一个字符串参数。

示例程序 2: 作为变量赋值

        这个示例展示了如何将匿名函数赋值给变量,并在后续调用这个变量。

package mainimport "fmt"func main() {// 将匿名函数赋值给变量 greetgreet := func(name string) {fmt.Printf("Hello, %s!\n", name)}// 调用函数greet("World")greet("Go")
}

        这里,匿名函数赋值给变量 greet,然后通过变量名调用该函数。

示例程序 3: 作为函数参数

        匿名函数可以作为参数传递给其他函数。这是在Go语言中实现回调或者定制行为的一种常用方式。

package mainimport "fmt"// 定义一个函数,接受另一个函数作为参数
func process(f func(string), value string) {f(value)
}func main() {// 调用 process,传递匿名函数和字符串参数process(func(s string) {fmt.Println(s)}, "Go is fun!")
}

        在这个例子中,process 函数接受一个函数作为参数。我们传递了一个匿名函数,它接受一个字符串参数并打印它。

示例程序 4: 使用匿名函数进行排序

        Go的sort.Slice函数允许使用匿名函数来定义排序逻辑。这是匿名函数作为功能参数的一个常见应用。

package mainimport ("fmt""sort"
)func main() {people := []struct {Name stringAge  int}{{"Alice", 23},{"Eve", 2},{"Bob", 25},}// 使用匿名函数进行排序,按年龄排序sort.Slice(people, func(i, j int) bool {return people[i].Age < people[j].Age})fmt.Println("Sorted by age:", people)
}

示例程序 5: 匿名函数用于延迟执行

        在Go中,defer语句常与匿名函数一起使用,以确保在函数返回前执行某些清理工作。

package mainimport "fmt"func main() {// 使用 defer 语句调用匿名函数defer func() {fmt.Println("Cleaning up!")}()fmt.Println("Doing some work...")// 当 main 函数返回时,会执行匿名函数中的打印语句
}

        这个示例展示了如何使用匿名函数进行资源清理或执行其他结束工作,这些工作会在当前函数结束时自动执行。

示例程序 6: 通过匿名函数实现迭代器

        匿名函数可以用来创建一个简单的迭代器,封装特定的迭代逻辑。

package mainimport "fmt"func newCounter() func() int {count := 0return func() int {count++return count}
}func main() {counter := newCounter()fmt.Println(counter()) // 输出 1fmt.Println(counter()) // 输出 2fmt.Println(counter()) // 输出 3// 创建另一个独立的计数器anotherCounter := newCounter()fmt.Println(anotherCounter()) // 输出 1
}

        在这个例子中,每次调用newCounter都会创建一个新的闭包,这个闭包维护自己的count状态,独立于其他闭包。

二、闭包用法

        Go语言中,闭包是一种函数,能够引用在其外部作用域定义的变量。由于闭包可以访问并操作这些变量,即使在它们的原始作用域已经结束后,它们被广泛用于创建具有私有状态的函数、实现回调函数和迭代器等。下面我将详细解释Go中闭包的基础知识,并提供几个实际项目中可能用到的示例。

基础知识

        在Go中,闭包通常是在一个函数内部创建的匿名函数,这个匿名函数访问外部函数的局部变量。这些变量随着匿名函数的存在而持续存在,即使外部函数的执行已经结束。

示例程序 1: 状态保持器

        使用闭包实现一个简单的状态保持器,这可以在需要对状态进行封装和管理时非常有用。

package mainimport "fmt"func stateHolder(initial int) func() int {state := initialreturn func() int {state++return state}
}func main() {counter := stateHolder(10)fmt.Println(counter()) // 输出 11fmt.Println(counter()) // 输出 12anotherCounter := stateHolder(20)fmt.Println(anotherCounter()) // 输出 21fmt.Println(anotherCounter()) // 输出 22
}

        在这个例子中,每个闭包都保持了自己的状态,互不影响。

示例程序 2: 生成器函数

        闭包可以用来创建生成器,例如生成连续的斐波那契数列。

package mainimport "fmt"func fibonacci() func() int {a, b := 0, 1return func() int {ret := aa, b = b, a+breturn ret}
}func main() {fib := fibonacci()for i := 0; i < 10; i++ {fmt.Println(fib())}
}

        这个生成器函数每次被调用时,都会返回序列中的下一个斐波那契数。

示例程序 3: 事件处理

        闭包可以用来处理事件或回调,使得状态和逻辑封装在一个单独的函数中。

package mainimport "fmt"type Button struct {onClick func()
}func NewButton() *Button {return &Button{onClick: func() {}}
}func main() {button := NewButton()count := 0button.onClick = func() {count++fmt.Printf("Button clicked %d times\n", count)}// 模拟点击事件button.onClick()button.onClick()button.onClick()
}

        这个示例中的闭包捕获了点击计数,并在每次点击时更新。

示例程序 4: 资源清理

        利用闭包在函数结束时进行资源清理。

package mainimport "fmt"func cleanup(resource string) func() {return func() {fmt.Printf("Cleaning up %s\n", resource)}
}func main() {defer cleanup("resourceA")()fmt.Println("Doing some work with resourceA")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java毕业设计 基于SpringBoot vue城镇保障性住房管理系统

Java毕业设计 基于SpringBoot vue城镇保障性住房管理系统 SpringBoot 城镇保障性住房管理系统 功能介绍 首页 图片轮播 房源信息 房源详情 申请房源 公示信息 公示详情 登录注册 个人中心 留言反馈 后台管理 登录 个人中心 修改密码 个人信息 用户管理 房屋类型 房源信息管理…

flutter利用get中的GetConnect实现拦截请求

1、baseProvider.dart 文件&#xff0c;里面实现请求的拦截和响应的处理 import dart:convert;import package:company_manage_flutter/config/setting.dart; import package:flutter_easyloading/flutter_easyloading.dart; import package:get/get_connect/connect.dart;cla…

Servlet和Tomcat运作过程

记录一下前后端请求交互过程&#xff08;不涉及Spring框架&#xff09;&#xff1a; 编写一个UserServlet 在web.xml文件中编写映射路径 编写前端

HTTP基础知识

1. HTTP常见的状态码有哪些&#xff1f; 常见状态码&#xff1a; 200&#xff1a;服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。 301 &#xff1a; (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时&a…

2024 OceanBase 开发者大会:OceanBase 4.3正式发布,打造近PB级实时分析数据库

4月20日&#xff0c;2024 OceanBase开发者大会盛大召开&#xff0c;吸引了50余位业界知名的数据库专家和爱好者&#xff0c;以及来自全国各地的近600名开发者齐聚一堂。他们围绕一体化、多模、TP与AP融合等前沿技术趋势展开深入讨论&#xff0c;分享场景探索的经验和最佳实践&a…

【基础篇】Git 基础命令与核心概念

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 一&#xff0c;Git 初识 1.1&#xff0c;问题引入 不知道你工作或学习时&#xff0c;有没有遇到…

Flutter 从 Assets 中读取 JSON 文件:指南 [2024]

在本教程中&#xff0c;我们将探讨如何从 Flutter 项目中的 asset 中读取 JSON 文件。您将找到详细的解释、实际示例和最佳实践&#xff0c;使您的 JSON 文件处理顺利高效。那么&#xff0c;让我们深入了解 Flutter 和 JSON 的世界吧&#xff01; 从 asset 中读取 JSON 文件 …

mpv启动脚本功能

要配置mpv以启用脚本功能&#xff0c;您可以按照以下步骤进行操作&#xff1a; 确保您已经安装了mpv播放器。您可以从mpv官方网站&#xff08;https://mpv.io/&#xff09;下载并安装适合您操作系统的版本。 打开mpv的配置文件。在Windows上&#xff0c;配置文件位于%APPDATA%…

与 Apollo 共创生态:Apollo 七周年大会给带来的震撼

文章目录 一、七年蛰伏&#xff0c;Apollo 迎来“智变”时刻二、Apollo 企业生态计划与开放平台2.1 Apollo X 企业自动驾驶解决方案2.2 Apollo 开放平台携手伙伴共创生态 三、个人感悟 一、七年蛰伏&#xff0c;Apollo 迎来“智变”时刻 让我们把时间倒回到 2013 年&#xff0…

微服务之分布式理论概述

一、分布式技术相关的理论 CAP理论 CAP定理(CAP theorem)&#xff0c;⼜被称作布鲁尔定理(Eric Brewer)&#xff0c;1998年第⼀次提出. 最初提出是指分布式数据存储不可能同时提供以下三种保证中的两种以上: (1) ⼀致性(Consistency): 每次读取收到的信息都是最新的; (2) …

玩转手机在AidLux上安装宝塔面板

AidLux&#xff0c;手机不用刷机、不用root&#xff0c;直接在手机应用市场就能下载使用。 1.4G的应用包&#xff0c;看起来挺大的&#xff0c;那是因为内嵌了一套完整的AIoT应用开发和部署平台。 不仅Android手机可以玩&#xff0c;华为的Harmony系统也可以使用。 使用它最主…

【声网】实现web端与uniapp微信小程序端音视频互动

实现web端与uniapp微信小程序端音视频互动 利用声网实现音视频互动 开通声网服务 注册声网账号 进入Console 成功登录控制台后&#xff0c;按照以下步骤创建一个声网项目&#xff1a; 展开控制台左上角下拉框&#xff0c;点击创建项目按钮。 在弹出的对话框内&#xff0c;依…

C++性能优化实践 三

C性能优化实践 三 文章目录 一、C标准库线程间的通信二、内存屏障、获得与释放语义三、多线程优化总结 书接上回, 这篇文章继续来谈谈C 并发编程性能优化相关的内容。 参考文章: hhttps://boolan.com/ 先形象的说明一下并发与并行: 并发&#xff1a;类似与足球场踢足球, 大家为…

python版的openCV使用及下载

一、下载OpenCV模块 截止目前&#xff1a;现在OpenCV使用环境还是python3.8的版本所以咱们下载时记得用3.8版本的 终端下载&#xff1a;pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python 这是国内的镜像下载能快一些&#xff1b; 下载成功的标志&am…

Linux简单命令

目录 显示目录下的内容 ls 切换工作目录 cd 查看-当前工作目录pwd 创建-文件夹 mkdir 创建-文件 touch 查看-文件内容 cat 查看-分屏查看文件内容 more 删除-文件、文件夹 rm 复制-文件、文件夹 cp 移动-文件、文件夹 mv 查找-命令的程序文件存放处 which 查找-按文…

Linux平台Unity下RTMP|RTSP低延迟播放器技术实现

技术背景 国产操作系统对于确保信息安全、促进技术创新、满足特定需求以及推动经济发展等方面都具有重要意义&#xff0c;多以Linux为基础二次开发。2014年4月8日起&#xff0c;美国微软公司停止了对Windows XP SP3操作系统提供支持&#xff0c;这引起了社会和广大用户的广泛关…

js的基础知识

给元素添加事件监听器 addEventListener介绍 addEventListener() 方法用于向指定元素添加事件处理程序&#xff08;事件句柄handler&#xff09;。 参数1&#xff1a;事件名称必须。字符串&#xff0c;指定事件名。 注意: 不要使用 “on” 前缀。 例如&#xff0c;使用 click…

SCI一区级 | Matlab实现BES-CNN-GRU-Mutilhead-Attention多变量时间序列预测

SCI一区级 | Matlab实现BES-CNN-GRU-Mutilhead-Attention秃鹰算法优化卷积门控循环单元融合多头注意力机制多变量时间序列预测 目录 SCI一区级 | Matlab实现BES-CNN-GRU-Mutilhead-Attention秃鹰算法优化卷积门控循环单元融合多头注意力机制多变量时间序列预测预测效果基本介绍…

Unreal Engine创建Plugin

打开UE工程&#xff0c;点击编辑&#xff0c;选择插件 点击“新插件”按钮&#xff0c;选择“空白选项”填入插件名字"MultiPlayerPlugin"&#xff0c;填入插件作者、描述&#xff0c;点击“创建插件”按钮打开C工程&#xff0c;即可看到插件目录&#xff0c;编译C工…

Linux网络编程---多进/线程并发服务器

一、多进程并发服务器 实现一个服务器可以连接多个客户端&#xff0c;每当accept函数等待到客户端进行连接时 就创建一个子进程 思路分析&#xff1a; 核心思路&#xff1a;让accept循环阻塞等待客户端&#xff0c;每当有客户端连接时就fork子进程&#xff0c;让子进程去和客户…