go 函数
go 语言函数
- go 函数
- 函数定义
- Go函数的特点如下
- 函数作为参数
- 可变参数
- 相同类型可变参数
- 不同类型可变参数
- return语句
- 作用概述
- 空的return语句
- 空白标识符
- 多个返回值
- 命名返回值
- defer 语句
- 作用
- 引申出来的面试题for defer
- 下面是一个使用`defer`的示例代码
- 输出结果
- 匿名函数
- 定义匿名函数
- 使用匿名函数
- 作用
- 使用注意事项
- 闭包
- 闭包定义
- 闭包的特点:
- 闭包的使用场景:
- 以下是一个使用闭包的示例代码:
go 函数
函数定义
在Go中,函数是一种基本的代码块,用于执行特定的任务。函数在Go中被定义为一个代码块,具有名称和一些参数,可以接受并返回值。函数定义如下:
func function_name(parameter_name type) return_type {// 函数体return value
}
其中,func
是关键字,function_name
是函数的名称,parameter_name
是参数的名称,type
是参数的数据类型,return_type
是函数的返回类型,value
是函数返回的值。
Go函数的特点如下
- 支持多返回值:Go语言的函数可以返回多个值,这样可以方便地返回多个计算结果或者同时处理多个返回值。
- 命名返回值:可以在函数定义时给返回值命名,使得函数内部可以直接使用这些变量,并且在函数结束时,可以通过简单的
return
语句来返回这些已命名的值。 - 支持可变参数:Go语言允许函数接受可变数量的参数。通过使用
...
语法,函数可以接受任意数量的相同类型参数。 - 支持defer语句:
defer
语句用于在函数执行完毕后,延迟执行指定的代码块。这在需要在函数返回前执行一些清理或资源释放操作时非常有用。 - 可以有多个
return
语句,但是只是会执行其中一个,执行后就会返回。 - 递归支持:Go语言支持递归函数,可以在函数体内调用自己,用于解决一些需要重复执行的问题。
- 支持错误处理:函数可以返回错误信息,用于指示函数执行中是否发生错误。Go鼓励使用多返回值来返回函数执行状态以及错误信息,以实现更可靠的错误处理机制。
- 函数作为一等公民:在Go语言中,函数可以像其他变量一样进行传递、赋值和作为参数传递给其他函数,作为返回值,这使得函数在Go中具有更强大的表现力和灵活性。
- 支持匿名函数和闭包:Go语言支持在函数内部定义匿名函数,并且这些函数可以捕获外部函数的局部变量,形成闭包。匿名函数是指没有名称的函数,可以直接将其赋值给变量或直接调用。
- 支持函数闭包:在Go中,可以在一个函数中定义另一个函数,内部函数可以访问外部函数的局部变量。这种特性被称为函数闭包,它可以用于实现一些更为复杂的逻辑和功能。闭包是指一个函数可以访问其外部作用域中的变量,即使该变量在函数外部也可以访问。
函数作为参数
在Go语言中,函数是一等公民,这意味着函数可以像其他变量一样被传递给其他函数,作为参数传递给其他函数。这样的特性使得函数更加灵活和强大,可以实现更为复杂的逻辑和功能。
在Go中,函数可以被声明为类型,例如:
type MyFunction func(int, int) int
上面的代码中,MyFunction
被声明为一个函数类型,它接受两个int
类型的参数并返回一个int
类型的值。
然后,我们可以在其他函数中使用这个函数类型作为参数,例如:
func calculate(a, b int, op MyFunction) int {return op(a, b)
}
在这个例子中,calculate
函数接受三个参数:两个int
类型的数值a
和b
,还有一个函数类型op
。该函数类型op
的签名必须和MyFunction
相同,接受两个int
类型参数并返回一个int
类型值。函数calculate
会将a
和b
作为参数传递给op
函数,并返回op
函数的结果。
使用示例:
func add(a, b int) int {return a + b
}func multiply(a, b int) int {return a * b
}func main() {result1 := calculate(2, 3, add) // 使用add函数进行加法运算,结果为5result2 := calculate(2, 3, multiply) // 使用multiply函数进行乘法运算,结果为6fmt.Println(result1, result2)
}
在上面的示例中,我们声明了add
和multiply
两个函数,并在main
函数中使用calculate
函数来执行加法和乘法运算,通过将不同的函数作为参数传递给calculate
函数,我们可以轻松地在calculate
函数中实现不同的操作,增加了代码的灵活性和可复用性。
函数作为参数的特性在Go语言中非常常用,它允许我们以一种通用的方式编写函数,以便在不同的场景下重用这些函数,并通过传递不同的函数作为参数来实现不同的功能。这种编程风格在编写高阶函数和实现回调机制时特别有用
可变参数
相同类型可变参数
在Go中,可以使用可变参数函数来接受不定数量的参数。这在需要传递不同数量参数的情况下非常有用。例如,fmt.Println() 函数可以接受不定数量的参数并将它们打印到控制台上。在Go中,使用可变参数函数时,需要在函数签名中指定 “…” 符号,表示参数数量不定。
下面是一个示例,演示了如何在Go中使用可变参数函数:
func sum(nums ...int) int {total := 0for _, num := range nums {total += num}return total
}func main() {fmt.Println(sum(1, 2, 3)) // 输出:6fmt.Println(sum(1, 2, 3, 4)) // 输出:10
}
在上面的代码中,函数 sum
声明了一个可变参数 nums
,表示可以接受任意数量的整数参数。在函数体内,我们使用 range 遍历了传入的参数,将它们相加后返回总和。
我们可以通过传递任意数量的参数来调用 sum
函数,示例中分别传递了 3 个参数和 4 个参数。函数会将它们全部相加并返回结果。
不同类型可变参数
在 Go 语言中,是可以传递多个不同类型的可变参数的。可以使用 interface{}
类型作为可变参数的类型,它可以表示任意类型的值。
下面是一个例子,展示了如何使用 interface{}
类型作为可变参数的类型,以便传递多个不同类型的值:
func printValues(values ...interface{}) {for _, value := range values {fmt.Println(value)}
}func main() {printValues(1, "two", true)
}
在上面的例子中,printValues
函数的可变参数类型被定义为 interface{}
,因此可以接受多个不同类型的值。在 main
函数中,我们传递了三个不同类型的值:整数、字符串和布尔值。在 printValues
函数中,我们使用 range
循环遍历所有传递进来的参数,并使用 fmt.Println
打印每个值。这样,我们就可以打印多个不同类型的值了。
return语句
作用概述
在Go中,return
语句用于从函数中返回值并停止函数执行,并把代码的执行权返回给调用者。对于无返回值的函数,函数体末尾的return语句可以直接省略。return
语句可以放在函数中的任何位置,并且可以返回零个、一个或多个值。
空的return语句
在无返回值函数(void函数)中,可以使用空的return语句来显式地结束函数的执行。
func doSomething() {// 一些操作return // 空的return语句表示函数执行结束
}
空白标识符
如果函数有命名返回值,但不打算在函数体中使用它们,可以使用下划线 _
作为空白标识符表示忽略这些返回值。
func divide(a, b float64) (result float64, err error) {// ...if b == 0 {err = fmt.Errorf("cannot divide by zero")return 0, err // 只返回错误,忽略result的返回值}// ...return // 只返回result,忽略err的返回值
}
多个返回值
在函数中,可以返回多个值,例如:
func calculate(a, b int) (int, int, int, float64) {sum := a + bdiff := a - bproduct := a * bquotient := float64(a) / float64(b)return sum, diff, product, quotient
}
在上面的例子中,calculate
函数返回四个值,它们是a
和b
的和、差、积和商。
命名返回值
在Go中,也可以在函数签名中为返回值指定名称,这些名称被视为函数的局部变量,在函数体中可以直接使用。如果在函数体中没有显式使用return语句,则返回值会自动被返回。例如:
func add(a, b int) (sum int) {sum = a + breturn
}
在上面的例子中,函数返回类型为int
,并且返回值被命名为sum
。在函数体中,sum
被计算为a
和b
的和,并通过不带参数的return
语句返回。
defer 语句
作用
- 在Go语言中,
defer
语句用于延迟执行一个函数调用,通常用于确保在函数执行完毕前进行一些清理操作。defer
语句会将函数调用推迟到包含它的函数即将返回之前执行,无论函数是正常返回还是发生了异常 - 在实际应用中,要确保在执行函数的过程中遇到错误时及时处理一些必要的事情,比如关闭连接、关闭文件等。通常情况下可以使用
defer
关键字实现这些功能。 defer
关键字用于释放资源,会在函数返回之前调用,即便函数崩溃也会在结束之前调用defer
。- 一个函数内可以有多个
defer
,在调用时按照栈的方式先进后出,即写在前面的后调用。
引申出来的面试题for defer
下面是一个使用defer
的示例代码
package mainimport "fmt"func main() {for i := 1; i <= 5; i++ {defer fmt.Println(i)}fmt.Println("Done")
}
输出结果
Done
5
4
3
2
1
在这个示例中,我们使用了一个for
循环,并在每次循环迭代时使用defer
语句延迟打印变量i
的值。当程序执行到defer fmt.Println(i)
时,不会立即执行该语句,而是在包含它的函数即将返回之前才执行。因此,打印的结果是逆序的。
需要注意的是,defer
语句是按照后进先出(LIFO)的顺序执行的。在示例代码中,我们使用了一个for
循环,每次循环迭代都会推迟一个新的defer
语句,所以在函数返回前,defer
语句会按照逆序执行。
总结起来,使用defer
语句可以确保在函数返回前执行一些必要的清理操作,而无需在每个可能的返回点都进行显式的调用。在使用defer
语句时需要注意推迟的函数调用的执行顺序,以及可能产生的副作用。
匿名函数
匿名函数是一种在Go语言中可以直接定义且没有函数名的函数。它是一种特殊类型的函数,可以在定义的地方直接使用,而不需要为其分配一个名字。匿名函数在Go中非常常用,特别是在需要传递函数作为参数、或者在闭包中使用时。
定义匿名函数
在Go语言中,定义匿名函数的一般形式为:
func(parameters) returnType {// function body
}
其中,parameters
表示函数的参数列表,returnType
表示函数的返回类型(可以省略),function body
表示函数体。
使用匿名函数
匿名函数可以直接在代码中使用,例如:
func main() {// 使用匿名函数计算两个数的和sum := func(a, b int) int {return a + b}(2, 3) // 调用匿名函数并传入参数2和3fmt.Println(sum) // 输出结果:5
}
在上面的例子中,我们定义了一个匿名函数并直接在代码中调用它,计算两个数的和并将结果存储在变量sum
中。
作用
匿名函数主要有两个作用:
- 作为参数传递:可以将匿名函数作为参数传递给其他函数,从而实现在函数中传递逻辑或行为。
- 闭包:匿名函数可以捕获外部函数中的变量,形成闭包。这意味着匿名函数可以访问外部函数的局部变量,即使外部函数已经执行完毕。
使用注意事项
在使用匿名函数时,需要注意以下几点:
- 调用匿名函数:定义匿名函数后,需要在定义后使用小括号
()
调用函数并传入参数(如果有参数的话)。 - 作为参数传递:可以将匿名函数作为参数传递给其他函数,以便在函数中执行匿名函数的逻辑。
- 闭包问题:在使用匿名函数时,尤其是在闭包中使用时,要注意外部变量的生命周期,确保不会出现意外的结果。
- 函数类型:匿名函数可以赋值给函数类型的变量,以便在其他地方使用。
- 变量作用域:在匿名函数中可以访问外部函数的局部变量,但要注意变量作用域的问题。
总结:匿名函数是Go语言中的一种强大特性,它可以简化代码并增加程序的灵活性。通过匿名函数,我们可以更加方便地编写高阶函数、实现闭包和实现回调机制,让我们的代码更加优雅和易于维护。但在使用匿名函数时,要特别注意变量作用域和闭包问题,避免出现不必要的错误。
闭包
闭包定义
闭包(Closure)是一个函数值(Function Value),它包含了函数的代码以及该函数的引用环境(变量)。
具体来说,闭包是指在函数内部定义的函数,这个内部函数可以访问其外部函数的局部变量,并且在外部函数的生命周期内都保持有效。闭包可以捕获和存储其外部函数的局部变量,并使得这些变量在内部函数被调用时保持状态。
闭包的特点:
- 内部函数可以访问外部函数的局部变量。
- 外部函数的局部变量被内部函数引用后,其生命周期得到延长,直到内部函数不再被引用时才会被销毁。
- 外部函数返回的是内部函数的函数值。
- 同一个闭包函数中的变量的生命周期是整个闭包函数的生命周期
闭包的使用场景:
- 常用于实现一些类似于对象的功能,隐藏了内部的状态信息,只提供对外暴露的方法。
- 用于实现回调机制,将函数作为参数传递给其他函数。
以下是一个使用闭包的示例代码:
package mainimport "fmt"func adder() func(int) int {sum := 0 // 外部函数的局部变量return func(x int) int {sum += x // 内部函数访问外部函数的局部变量return sum}
}func main() {// 创建一个闭包函数,该函数可以累加传入的参数myAdder := adder()// 调用闭包函数,实现累加fmt.Println(myAdder(1)) // 输出结果:1fmt.Println(myAdder(2)) // 输出结果:3fmt.Println(myAdder(3)) // 输出结果:6
}
在上面的例子中,我们定义了一个外部函数adder
,它返回了一个闭包函数。闭包函数中引用了外部函数的局部变量sum
,并可以持续地累加传入的参数。每次调用myAdder
函数,都会保留之前的sum
值,并在原来的基础上继续累加。这就是闭包的特性,使得局部变量sum
的生命周期得到了延长,并在多次调用中保持了状态。
闭包在Go语言中是一种非常有用且强大的特性,可以用于简化代码、实现高阶函数和实现回调机制。但在使用闭包时,要注意不要滥用闭包,避免造成资源泄漏或不必要的性能损失。
相关文章:
go 函数
go 语言函数 go 函数函数定义Go函数的特点如下函数作为参数可变参数相同类型可变参数不同类型可变参数 return语句作用概述空的return语句空白标识符多个返回值命名返回值 defer 语句作用引申出来的面试题for defer下面是一个使用defer的示例代码输出结果 匿名函数定义匿名函数…...
python之正则表达式
目录 正则表达式 python正则表达式方法 match search findall finditer compile 元字符匹配 元字符 量词 贪婪匹配和惰性匹配 正则表达式的group 语法 案例 正则表达式 正则表达式又称规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串…...

【LeetCode每日一题】——219.存在重复元素II
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 哈希表 二【题目难度】 简单 三【题目编号】 219.存在重复元素II 四【题目描述】 给你一个…...
篇六:适配器模式:让不兼容变兼容
篇六:“适配器模式:让不兼容变兼容” 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/ 另外有2本不错的关于设计模式的资料,…...

【云原生】Docker-compose中所有模块学习
compose模块 模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的。 默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。 version: "3&quo…...
广义积分练习
前置知识 无穷限积分瑕积分 练习 计算 ∫ 0 ∞ 1 x ( 1 x ) d x \int_0^{\infty}\dfrac{1}{\sqrt x(1x)}dx ∫0∞x (1x)1dx 解: x 0 \qquad x0 x0为瑕点 \qquad 原式 lim a → 0 lim b → ∞ ∫ a b 1 x ( 1 x ) d x lim a → 0 lim …...

element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)
功能如图 功能需求 表格树形表格勾选数据,右边显示对应勾选的数据内容,选中客户,自动勾选所有的店铺(子级),选中其中一个店铺,自动勾选上客户(父级),同时会存在只有客户(下面没有子级的情况&am…...
Android数字价格变化的动画效果的简单实现
原理:使用ValueAnimator属性动画类实现,它通过值的改变手动设置对象的属性值来实现动画效果。直接贴代码: public static void doNumberAnim(TextView tvPrice, float startNumber, float endNumber) {ValueAnimator animator ValueAnimato…...

Win10无法投影关闭3D模式
Win10不小心开启了3D模式,插上投影仪就一闪一闪的,无法正投影 解决办法: 1. 打开注册表工具regedit,删除以下注册表,重启电脑 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configurat…...

FFmpeg 编码详细流程
介绍 FFmpeg的 libavcodec 模块完成音视频多媒体的编解码模块。FFmpeg 本身不具有音视频编码的功能和底层能力,只是对各类第三方的编码器API 进行封装调用。老版本的 FFmpeg 将avcodec_encode_video2()作为视频的解码函数 API,将avcodec_encode_audio2(…...
05如何做微服务架构设计
一句话导读 微服务架构设计方法有:领域驱动设计DDD(Domain-Driven-Design)、12因素应用(12-Factor App)、事件驱动架构EDA(Event-Driven Architecture)等等,但是他们都必须遵守微服务…...

安卓开发问题记录:需要常量表达式
问题原因 写代码过程中爆出这个错误:需要常量表达式,定位到switch。 解决方法:把switch case,改成if else 错误源代码: public void onClick(View view) {switch (view.getId()) {case R.id.iv_code:RxCaptcha.build(…...

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测
回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测预测效果基本介绍研究内容程序设计参考资料…...

配置root账户ssh免密登录并使用docker-machine构建docker服务
简介 Docker Machine是一种可以在多种平台上快速安装和维护docker运行环境,并支持多种平台,让用户可以在很短时间内在本地或云环境中搭建一套docker主机集群的工具。 使用docker-machine命令,可以启动、审查、停止、重启托管的docker 也可以…...
【力扣周赛】第357场周赛
【力扣周赛】第357场周赛 2810. 故障键盘题目描述解题思路 2811. 判断是否能拆分数组题目描述解题思路 2810. 故障键盘 题目描述 描述:你的笔记本键盘存在故障,每当你在上面输入字符 ‘i’ 时,它会反转你所写的字符串。而输入其他字符则可以…...

多线程案例(4)-线程池
文章目录 多线程案例四四、线程池 大家好,我是晓星航。今天为大家带来的是 多线程案例-线程池 相关的讲解!😀 多线程案例四 四、线程池 线程池是什么 虽然创建线程 / 销毁线程 的开销 想象这么一个场景: 在学校附近新开了一家…...

【数据结构OJ题】轮转数组
原题链接:https://leetcode.cn/problems/rotate-array/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 1. 方法一:暴力求解,将数组的第一个元素用临时变量tmp存起来,再将数组其他元素往右挪动一步&…...

现代C++中的从头开始深度学习:【4/8】梯度下降
一、说明 在本系列中,我们将学习如何仅使用普通和现代C编写必须知道的深度学习算法,例如卷积、反向传播、激活函数、优化器、深度神经网络等。 在这个故事中,我们将通过引入梯度下降算法来介绍数据中 2D 卷积核的拟合。我们将使用卷积和上一个…...

Yolov5缺陷检测/目标检测 Jetson nx部署Triton server
使用AI目标检测进行缺陷检测时,部署到Jetson上即小巧算力还高,将训练好的模型转为tensorRT再部署到Jetson 上供http或GRPC调用。1 Jetson nx 刷机 找个ubuntu 系统NVIDIA官网下载安装Jetson 的sdkmanager一步步刷机即可。 本文刷的是JetPack 5.1, 其中包…...

MobaXterm 中文乱码, 及pojie
中文解决方法: 把“连字”去掉! MobaXterm网页,可以生成一个授权文件Custom.mxtpro。放在安装目录就可以了 MobaXterm Keygen (husbin.top)http://b70.husbin.top:5000/...

如何使用CodeRider插件在IDEA中生成代码
一、环境搭建与插件安装 1.1 环境准备 名称要求说明操作系统Windows 11JetBrains IDEIntelliJ IDEA 2025.1.1.1 (Community Edition)硬件配置推荐16GB内存50GB磁盘空间 1.2 插件安装流程 步骤1:市场安装 打开IDEA,进入File → Settings → Plugins搜…...

【自然语言处理】大模型时代的数据标注(主动学习)
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构D 实验设计E 个人总结 A 论文出处 论文题目:FreeAL: Towards Human-Free Active Learning in the Era of Large Language Models发表情况:2023-EMNLP作者单位:浙江大…...

【Redis】Redis 的持久化策略
目录 一、RDB 定期备份 1.2 触发方式 1.2.1 手动触发 1.2.2.1 自动触发 RDB 持久化机制的场景 1.2.2.2 检查是否触发 1.2.2.3 线上运维配置 1.3 检索工具 1.4 RDB 备份实现原理 1.5 禁用 RDB 快照 1.6 RDB 优缺点分析 二、AOF 实时备份 2.1 配置文件解析 2.2 开启…...
云原生技术驱动 IT 架构现代化转型:企业实践与落地策略全解
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、背景:IT 架构演进的战略拐点 过去十年,企业 IT 架构经历了从传统集中式架构到分布式架构的转型。进入云计算…...

夏普比率(Sharpe ratio)
具有投资常识的人都明白,投资光看收益是不够的,还要看承受的风险,也就是收益风险比。 夏普比率描述的正是这个概念,即每承受一单位的总风险,会产生多少超额的报酬。 用数学公式描述就是: 其中࿱…...

(33)课54:3 张表的 join-on 连接举例,多表查询总结。数据库编程补述及游标综合例题。静态 sqL与动态sqL(可带参数)
(112)3 张表的 join-on 连接举例 : (113) 多表查询总结 : (114)数据库编程补述 : 综合例题 : 以上没有动手练习,不知道这样的语法是否…...
Vue3 + TypeSrcipt 防抖、防止重复点击实例
需要实现防抖应用场景: 点击【查询】按钮,发送网络请求,等待并接收响应数据 原来点击【查询】的代码: <script setup lang"ts" name"ReagentTransactionsDrawer"> ...... // 查询,没有防…...
Elasticsearch 常用操作命令整合 (cURL 版本)
Elasticsearch 常用操作命令整合 (cURL 版本) 集群管理 查看集群健康状态 curl -X GET "localhost:9200/_cluster/health?pretty"查看节点信息 curl -X GET "localhost:9200/_cat/nodes?v"查看集群统计信息 curl -X GET "localhost:9200/_clus…...

Vue部署到Nginx上及问题解决
一、Vue打包 dist文件即打包文件 二、下载Nginx,将dist内容全部复制到Nginx的html下 三、修改Nginx的nginx.conf配置文件,添加try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html; 是 Nginx 配置中的一个重要指令,用于处理…...
四自由度机械臂Simulink仿真设计与实现
四自由度机械臂Simulink仿真设计与实现 摘要 本文详细介绍了基于MATLAB/Simulink的四自由度机械臂建模、仿真与控制实现。通过建立完整的运动学和动力学模型,设计PID控制器,实现轨迹跟踪功能,并利用3D可视化技术进行仿真验证。全文涵盖理论建模、Simulink实现和仿真分析三…...