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/...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
