Go基础编程:递归函数、函数类型、匿名函数与闭包

2024-03-24 21:32

本文主要是介绍Go基础编程:递归函数、函数类型、匿名函数与闭包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 递归函数

递归指函数可以直接或间接的调用自身。

递归函数通常有相同的结构:一个跳出条件和一个递归体。所谓跳出条件就是根据传入的参数判断是否需要停止递归,而递归体则是函数自身所做的一些处理。

//通过循环实现1+2+3……+100
func Test01() int {i := 1sum := 0for i = 1; i <= 100; i++ {sum += i}return sum
}

//通过递归实现1+2+3……+100
func Test02(num int) int {if num == 1 {return 1}return num + Test02(num-1) //函数调用本身
}

//通过递归实现1+2+3……+100
func Test03(num int) int {if num == 100 {return 100}return num + Test03(num+1) //函数调用本身
}func main() {fmt.Println(Test01())    //5050fmt.Println(Test02(100)) //5050fmt.Println(Test03(1))   //5050
}

2. 函数类型

在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。

type FuncType func(int, int) int //声明一个函数类型, func后面没有函数名//函数中有一个参数类型为函数类型:f FuncType
func Calc(a, b int, f FuncType) (result int) {result = f(a, b) //通过调用f()实现任务return
}func Add(a, b int) int {return a + b
}func Minus(a, b int) int {return a - b
}func main() {//函数调用,第三个参数为函数名字,此函数的参数,返回值必须和FuncType类型一致result := Calc(1, 1, Add)fmt.Println(result) //2var f FuncType = Minusfmt.Println("result = ", f(10, 2)) //result =  8
}

3. 匿名函数与闭包

所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

在Go语言里,所有的匿名函数(Go语言规范中称之为函数字面量)都是闭包。匿名函数是指不需要定义函数名的一种函数实现方式,它并不是一个新概念,最早可以回溯到1958年的Lisp语言。

func main() {i := 0str := "mike"//方式1f1 := func() { //匿名函数,无参无返回值//引用到函数外的变量fmt.Printf("方式1:i = %d, str = %s\n", i, str)}f1() //函数调用//方式1的另一种方式type FuncType func() //声明函数类型, 无参无返回值var f2 FuncType = f1f2() //函数调用//方式2var f3 FuncType = func() {fmt.Printf("方式2:i = %d, str = %s\n", i, str)}f3() //函数调用//方式3func() { //匿名函数,无参无返回值fmt.Printf("方式3:i = %d, str = %s\n", i, str)}() //别忘了后面的(), ()的作用是,此处直接调用此匿名函数//方式4, 匿名函数,有参有返回值v := func(a, b int) (result int) {result = a + breturn}(1, 1) //别忘了后面的(1, 1), (1, 1)的作用是,此处直接调用此匿名函数, 并传参fmt.Println("v = ", v)}

闭包捕获外部变量特点:

func main() {i := 10str := "mike"func() {i = 100str = "go"//内部:i = 100, str = gofmt.Printf("内部:i = %d, str = %s\n", i, str)}() //别忘了后面的(), ()的作用是,此处直接调用此匿名函数//外部:i = 100, str = gofmt.Printf("外部:i = %d, str = %s\n", i, str)
}

函数返回值为匿名函数:

// squares返回一个匿名函数,func() int
// 该匿名函数每次被调用时都会返回下一个数的平方。
func squares() func() int {var x intreturn func() int {//匿名函数x++ //捕获外部变量return x * x}
}func main() {f := squares()fmt.Println(f()) // "1"fmt.Println(f()) // "4"fmt.Println(f()) // "9"fmt.Println(f()) // "16"
}

函数squares返回另一个类型为 func() int 的函数。对squares的一次调用会生成一个局部变量x并返回一个匿名函数。每次调用时匿名函数时,该函数都会先使x的值加1,再返回x的平方。第二次调用squares时,会生成第二个x变量,并返回一个新的匿名函数。新匿名函数操作的是第二个x变量。

通过这个例子,我们看到变量的生命周期不由它的作用域决定:squares返回后,变量x仍然隐式的存在于f中。

这篇关于Go基础编程:递归函数、函数类型、匿名函数与闭包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842851

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

Go信号处理如何优雅地关闭你的应用

《Go信号处理如何优雅地关闭你的应用》Go中的优雅关闭机制使得在应用程序接收到终止信号时,能够进行平滑的资源清理,通过使用context来管理goroutine的生命周期,结合signal... 目录1. 什么是信号处理?2. 如何优雅地关闭 Go 应用?3. 代码实现3.1 基本的信号捕获和优雅关闭3.2

C# dynamic类型使用详解

《C#dynamic类型使用详解》C#中的dynamic类型允许在运行时确定对象的类型和成员,跳过编译时类型检查,适用于处理未知类型的对象或与动态语言互操作,dynamic支持动态成员解析、添加和删... 目录简介dynamic 的定义dynamic 的使用动态类型赋值访问成员动态方法调用dynamic 的

C#反射编程之GetConstructor()方法解读

《C#反射编程之GetConstructor()方法解读》C#中Type类的GetConstructor()方法用于获取指定类型的构造函数,该方法有多个重载版本,可以根据不同的参数获取不同特性的构造函... 目录C# GetConstructor()方法有4个重载以GetConstructor(Type[]

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal