3.5 Go(特殊函数)
目录
一、匿名函数
1、匿名函数的特点:
2、匿名函数代码示例
2、匿名函数的类型
二、递归函数
1. 递推公式版本
2. 循环改递归
三、嵌套函数
1、嵌套函数用途
2、代码示例
3、作用域 & 变量生存周期
四、闭包
1、闭包使用场景
2、代码示例
五、Defer
1、defer 关键特点
2、defer 代码示例
3、defer 在 return 之后执行
4、defer 绑定的是“实参值”,执行顺序遵循 LIFO
一、匿名函数
匿名函数是没有名称的函数,通常在定义时直接使用其功能,而不需要为其命名。匿名函数的定义一般是在代码中动态地创建并立即使用。
1、匿名函数的特点:
• 无名称:与普通函数不同,匿名函数不需要指定名字。
• 即时使用:常用于需要临时函数的场景,尤其是作为参数传递给其他函数。
应用场景
匿名函数的应用广泛,尤其是在以下两种情况下:
1. 回调函数:匿名函数常作为回调函数使用,尤其是在处理异步操作时。例如,JavaScript中的事件监听、Go中的channel处理等。
2、匿名函数代码示例
- 匿名函数被作为回调来处理异步任务。
func() {fmt.Println("异步操作完成!")
}()
钩子函数(Hook):钩子函数允许在特定事件发生时执行额外的代码。匿名函数可以作为钩子函数,方便在特定逻辑中插入自定义操作。
type Hook func()func RegisterHook(h Hook) {h()
}func main() {RegisterHook(func() {fmt.Println("执行钩子函数!")})
}
2、匿名函数的类型
匿名函数与命名函数一样,也有自己的输入参数和输出参数,并且可以像普通函数一样进行类型定义。匿名函数的类型由其参数类型和返回值类型来决定。
• 入参和出参一致的函数:如果两个匿名函数的输入参数和返回值类型完全相同,我们称这两个函数为相同类型的匿名函数。即使它们的具体实现不同,只要入参和出参相同,它们就可以互换使用。
• 函数体不同:类型相同的匿名函数不代表它们的具体实现逻辑必须一样。即使两个匿名函数的入参、出参相同,它们在处理逻辑上的实现可以完全不同。
二、递归函数
递归(Recursion)是一种 函数自己调用自己 的编程技巧,通常用于解决 分解问题 和 重复子问题 的场景,比如 阶乘、斐波那契数列、树遍历 等。
递归的关键点
1.边界条件(Base Case): 防止无限递归,确保递归能终止。
2.递归前进(Recursive Case): 递归调用自身,逐步逼近边界条件。
3.递归返回(Return Phase): 当达到边界条件时,返回结果,逐层回溯。
递归实现方式
1. 递推公式版本
适用于具有明显的数学递推公式的问题,如 阶乘、斐波那契数列 等。
计算 n 的阶乘(n!)
阶乘公式:
n! = n \times (n-1)!, 当 n > 1 时
0! = 1, 递归终止条件
package mainimport "fmt"// 递归实现阶乘
func factorial(n int) int {// 递归终止条件if n == 0 {return 1}// 递归前进:n * (n-1)!return n * factorial(n-1)
}func main() {fmt.Println("5 的阶乘是:", factorial(5)) // 输出 120
}
2. 循环改递归
有些递归实现的算法可以改用循环来提高效率,比如斐波那契数列。
package mainimport "fmt"// 斐波那契数列(循环版)
func fibonacciLoop(n int) int {if n == 0 {return 0}if n == 1 {return 1}a, b := 0, 1for i := 2; i <= n; i++ {a, b = b, a+b}return b
}func main() {fmt.Println("斐波那契数列前10项(循环版):")for i := 0; i < 10; i++ {fmt.Print(fibonacciLoop(i), " ")}
}
三、嵌套函数
1、嵌套函数用途
逻辑封装,避免代码重复
当某些操作只在特定函数内部使用,并且不会被外部调用时,可以使用嵌套函数来减少代码重复,提升代码可读性。
2、代码示例
函数中定义另外一个函数,
函数嵌套形成嵌套作用域
package mainimport "fmt"// 函数嵌套形成嵌套作用域
func outer() {c := 99var inner = func() {c = 100 //修改outer的c值,修改完成后会覆盖outer,其实修改的outer 上的变量内容fmt.Println("inner c==", c, &c) //对outer的c进行赋值修改c := c + 1 //inner的局部变量,外部无法调用。fmt.Println("inner c==", c, &c)}inner()fmt.Println("outer c==", c, &c)}func main() {outer() //先执行inner函数}
3、作用域 & 变量生存周期
在 Go 语言中,变量的作用域决定了它的 生存周期 和 可访问性:
1. 全局作用域:在 package 级别定义的变量,整个包都能访问。
2. 函数作用域:在函数内定义的变量,只有这个函数可以访问。
3. 嵌套作用域:
- inner() 可以访问 outer() 的 c(因为 Go 支持闭包)。
- 但 inner() 不能修改 outer() 的 c 的地址,只能修改其值。
四、闭包
1、闭包使用场景
闭包使用的原因,解决栈帧消亡后值不能消失。变量从栈中逃逸到堆上,本次调用的栈消亡,堆不消亡
2、代码示例
func outer() func() {c := 99 // 变量 c 在 outer 作用域内var inner = func() {fmt.Println("1 inner c==", c, &c) // 这里 c 仍然是 outer 作用域的变量}fmt.Println("2 outer c==", c, &c) // 这里打印 outer 内的 creturn inner // 返回 inner 函数,但并不调用它
}
outer() 里定义了 c,然后 inner 函数捕获了 c,但 inner 并没有被执行,而是作为返回值返回。
• outer() 先执行,打印 c 的值和地址。
• main() 里 fn := outer(),将 inner 赋值给 fn,但 inner 还未执行,所以 c 依然没有被打印或修改。
• fmt.Println(fn) 只是打印 fn 这个函数本身的地址,而 inner 仍然未执行。
• inner 形成闭包,捕获 c,并且 c 不会因为 outer 结束而消失。
• 只有当 fn() 被执行时,inner 才会访问 c 并打印它。
• 由于 c 被 inner 捕获,它存活的时间超出了 outer 的生命周期(变量逃逸到堆上)。
五、Defer
defer 关键字用于推迟执行某个函数,直到**当前函数返回(正常 return 或 panic 发生时)**才会执行。
1、defer 关键特点
1. 延迟执行:defer 语句不会立即执行,而是在当前函数返回时执行。
2. 执行顺序:LIFO(后进先出),即多个 defer 按照注册顺序的反向顺序执行。
3. 保证执行:无论是正常返回(return)还是异常崩溃(panic),defer 代码块都会执行。
4. 不执行的情况:os.Exit() 或 log.Fatal() 会导致程序立即退出,使 defer 代码块无法执行。
2、defer 代码示例
package mainimport "fmt"func main() {defer fmt.Println("1") // 最后执行defer fmt.Println("2") // 倒数第二执行defer fmt.Println("3") // 倒数第三执行fmt.Println("start")fmt.Println("stop")
}
代码输出结果:
start
stop
3
2
1
fmt.Println("start") 立即执行
• fmt.Println("stop") 立即执行
• defer 语句按照 后进先出 顺序执行
3、defer 在 return 之后执行
package mainimport "fmt"func test() {defer fmt.Println("defer 执行")fmt.Println("函数内执行")return
}func main() {test()fmt.Println("函数返回后执行")
}
输出结果:
函数内执行
defer 执行
函数返回后执行
4、defer 绑定的是“实参值”,执行顺序遵循 LIFO
package mainimport ("fmt"
)func main() {a := 1024fmt.Println("start ~~~~~~~~~~~~~~")defer fmt.Println(a) // defer 1: 绑定值 1024a++ // a = 1025defer fmt.Println(a) // defer 2: 绑定值 1025a++ // a = 1026defer fmt.Println(a) // defer 3: 绑定值 1026a++ // a = 1027fmt.Println("stop~~~~~~~~~~~~~~~~")
}
输出结果
start ~~~~~~~~~~~~~~
stop~~~~~~~~~~~~~~~~
1026
1025
1024
代码执行时,defer 语句在注册时就会确定参数的值,不会受到后续 a 值变化的影响。
defer 语句执行时,实参值已经确定
• defer fmt.Println(a) 注册时,参数 a 当前的值会被存下来,后续 a 的变化不会影响 defer 绑定的值。
• 多个 defer 语句按 LIFO 顺序执行(后进先出)。
相关文章:
3.5 Go(特殊函数)
目录 一、匿名函数 1、匿名函数的特点: 2、匿名函数代码示例 2、匿名函数的类型 二、递归函数 1. 递推公式版本 2. 循环改递归 三、嵌套函数 1、嵌套函数用途 2、代码示例 3、作用域 & 变量生存周期 四、闭包 1、闭包使用场景 2、代码示例 五、De…...
Android的MQTT客户端实现
在 Android 平台上实现 MQTT 客户端的完整技术方案,涵盖基础实现、安全连接、性能优化和最佳实践: 一、技术选型与依赖配置 推荐库 Eclipse Paho Android Service(官方维护,支持后台运行) gradle 复制 // build.gradl…...

国产编辑器EverEdit - 编辑辅助功能介绍
1 编辑辅助功能 1.1 各编辑辅助选项说明 1.1.1 行号 打开该选项时,在编辑器主窗口左侧显示行号,如下图所示: 1.1.2 文档地图 打开该选项时,在编辑器主窗口右侧靠近垂直滚动条的地方显示代码的缩略图,如下图所示&…...
WPF 在后台使TextBox失去焦点的方法
在软件设计开发的时候,偶尔会遇到在后台xaml.cs后台中,要将TextBox控件的焦点取消或者使TextBox控件获取焦点,下面介绍讲述一种简单的“只让特定的 TextBox 失去焦点”方法: 前端xaml代码示例: <StackPanel Orientation"…...

工作案例 - python绘制excell表中RSRP列的CDF图
什么是CDF图 CDF(Cumulative Distribution Function)就是累积分布函数,是概率密度函数的积分。CDF函数是一个在0到1之间的函数,描述了随机变量小于或等于一个特定值的概率。在可视化方面,CDF图表明了一个随机变量X小于…...

CTF SQL注入学习笔记
部分内容来自于SQL注入由简入精_哔哩哔哩_bilibili SQL语句 1.mysqli_error():返回最近调用函数的最后一个错误描述 语法:mysqli_error(connection) 规定要使用的Mysql连接; 返回一个带有错误描述的字符串。如果没有错误发生则返回 "" 2…...
element-plus el-tree-select 修改 value 字段
element-plus el-tree-select 修改 value 字段 ,不显示label 需要注意两个地方: <el-tree-select v-model"value" :data"data" multiple :render-after-expand"false" show-checkbox style"width: 240px" …...

基于javaweb的SpringBoot小区智慧园区管理系统(源码+文档+部署讲解)
🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 运行环境开发工具适用功能说明 运行环境 Java≥8、MySQL≥5.7、Node.js≥14 开发工具 后端:eclipse/idea/myeclipse…...

SpringBoot学习之shardingsphere实现分库分表(基于Mybatis-Plus)(四十九)
一、shardingsphere介绍 ShardingSphere是一款起源于当当网内部的应用框架。2015年在当当网内部诞生,最初就叫ShardingJDBC。2016年的时候,由其中一个主要的开发人员张亮,带入到京东数科,组件团队继续开发。在国内历经了当当网、电信翼支付、京东数科等多家大型互联网企业的…...

23.PPT:校摄影社团-摄影比赛作品【5】
目录 NO12345 NO6 NO7/8/9/10 单元格背景填充表格背景填充文本框背景填充幻灯片背景格式设置添加考生文件夹下的版式 NO12345 插入幻灯片和放入图片☞快速:插入→相册→新建相册→文件→图片版式→相框形状→调整边框宽度左下角背景图片:视图→…...

Baumer工业相机堡盟相机的相机传感器芯片清洁指南
Baumer工业相机堡盟相机的相机传感器芯片清洁指南 Baumer工业相机1.Baumer工业相机传感器芯片清洁工具和清洁剂2.Baumer工业相机传感器芯片清洁步骤2.1、准备步骤2.2、清洁过程1.定位清洁工具2.清洁传感器3.使用吹风装置 Baumer工业相机传感器芯片清洁的优势设计与结…...
Spring Boot 整合 JPA 实现数据持久化
目录 前言 一、JPA 核心概念与实体映射 1. 什么是 JPA? 2. JPA 的主要组件 3. 实体映射 4. 常见的字段映射策略 二、Repository 接口与自定义查询 1. 什么是 Repository 接口? 2. 动态查询方法 3. 自定义查询 4. 分页与排序 三、实战案例&…...

快速在wsl上部署学习使用c++轻量化服务器-学习笔记
知乎上推荐的Tinywebserver这个服务器,快速部署搭建,学习c服务器开发 仓库地址 githubhttps://link.zhihu.com/?targethttps%3A//github.com/qinguoyi/TinyWebServerhttps://link.zhihu.com/?targethttps%3A//github.com/qinguoyi/TinyWebServer 在…...

【R语言】数据操作
一、查看和编辑数据 1、查看数据 直接打印到控制台 x <- data.frame(a1:20, b21:30) x View()函数 此函数可以将数据以电子表格的形式进行展示。 用reshape2包中的tips进行举例: library("reshape2") View(tips) head()函数 查看前几行数据&…...

MariaDB MaxScale实现mysql8主从同步读写分离
一、MaxScale基本介绍 MaxScale是maridb开发的一个mysql数据中间件,其配置简单,能够实现读写分离,并且可以根据主从状态实现写库的自动切换,对多个从服务器能实现负载均衡。 二、MaxScale实验环境 中间件192.168.121.51MaxScale…...

【python】简单的flask做页面。一组字母组成的所有单词。这里的输入是一组字母,而输出是所有可能得字母组成的单词列表
目录结构如下: https://github.com/kaede316/Pythons_pj.git 效果: 后续可扩展为工具网站: 更新 2025.02.09 1、增加等间距制作人 时间信息 2、增加判断润年的功能...

单片机之基本元器件的工作原理
一、二极管 二极管的工作原理 二极管是一种由P型半导体和N型半导体结合形成的PN结器件,具有单向导电性。 1. PN结形成 P型半导体:掺入三价元素,形成空穴作为多数载流子。N型半导体:掺入五价元素,形成自由电子作为多…...

吴恩达深度学习——卷积神经网络的特殊应用
内容来自https://www.bilibili.com/video/BV1FT4y1E74V,仅为本人学习使用。 文章目录 人脸识别相关定义Similarity函数使用Siamese网络实现函数d使用Triplet损失学习参数 神经风格迁移深度卷积网络可视化神经风格迁移的代价函数内容损失函数风格损失函数 人脸识别 …...

安宝特方案 | AR助力制造业安全巡检智能化革命!
引言: 在制造业中,传统巡检常面临流程繁琐、质量波动、数据难以追溯等问题。安宝特AR工作流程标准化解决方案,通过增强现实AR技术,重塑制造业安全巡检模式,以标准化作业流程为核心,全面提升效率、质量与…...

Unity-Mirror网络框架-从入门到精通之Discovery示例
文章目录 前言Discovery示例NetworkDiscoveryNetworkDiscoveryHUDServerRequestServerResponse最后前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。本系列文章将为读者提供对Mirror网络框架的深入了解,涵盖从基础到高级的多个主题。Mirror是一个用于Un…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...