目录
1.构造一个闭包,输入文件名时,为其添加相应后缀,如输入文件名"hello",输出"hello.jpg"
2.使用递归实现爬楼梯:即某人一次只能爬1级或2级阶梯,当输入阶梯数量i时,要求输出一共有多少种走法去爬楼梯。
前言
本文将详细介绍GO语言中的函数使用,包括函数的定义,函数的类型,匿名函数,回调函数,闭包以及递归函数的使用等。
一、Go语言中函数如何定义?
1.函数的定义方式
在Go语言中,函数通过func关键字进行定义或声明。函数具有参数列表和返回值列表,参数列表可以有0个或多个参数,返回值列表也可以有0个或多个返回值。
2.函数的类型
// 1.函数的4种类型,无参无返回值,无参有返回值,有参无返回值,有参有返回值
func f1 ()(){
fmt.Println("I am f1()")
}
func f2()int{
fmt.Println("I am f1(),i will return an int num")
return 5
}
func f3(i int){
fmt.Printf("I am f3(),i got an int num:%v\n",i)
}
func f4(i int)int{
fmt.Printf("I am f3(),i got an int num:%v,i will return it \n",i)
return i
}
func main(){
fmt.Printf("%T,%T,%T,%T\n",f1,f2,f3,f4) //输出:func(),func() int,func(int),func(int) int
}
函数的类型包括其参数列表及返回值列表
二、函数的使用
1.匿名函数
- 有时候我们想要完成某一特定功能,但该功能只在一个包中用到几次,我们可以不用将其封装为包级别的函数,而是使用匿名函数
- 匿名函数,就是可以省略函数名的函数
r := func (i int)int{ // 匿名函数不需要函数名 return i }(5) // 匿名函数通过后面的()向函数传参 fmt.Println(r) // 输出5
2.回调函数
go语言是一种强类型语言,我们知道了函数的类型,就可以将其作为参数传入另一个函数,我们称这种函数为回调函数。
func f5(i int,callback func(i int)bool){
if callback(i){
fmt.Println("i am more than 5")
}else{
fmt.Println("i am less than 5")
}
}
func main(){
callback := func(i int)bool{
if i > 5{
return true
}
return false
}
f5(7,callback) // 输出i am more than 5
}
3.闭包
刚刚讨论了函数作为函数参数的情况,现在再来讨论函数作为返回值的情况。在一个函数中返回值是另外一个函数,我们称之为闭包。
- 闭包的理解:内部函数访问外部函数的变量
- 闭包的作用:改变临时变量的生命周期
- 闭包示例
// 考虑这样一种应用场景,公司其他部门的同事提供给你API,该API要求输入参数为一个func()类型(无参数无返回值) // 现在你有一个func(i int)类型的函数,如何才能调用上述的API呢,这就需要用到闭包 func f6(f func()){ fmt.Println("I am f6()") f() } func f7(i int)func(){ return func(){ // 可以看到,该匿名函数中并没有关于变量i的声明与定义,它引用了外部f7()的变量,延长了变量i的生命周期 fmt.Printf("I am f7(),i have a parameter:%v\n",i) } } func main(){ f6(f7(9)) // 输出:I am f6() \n I am f7(),i have a parameter:9 }
4.递归
- 函数在处理过程中调用自身,称之为递归。
- 递归必须有结束条件,否则会陷入死循环。
- 使用递归前,最好把问题进行数学抽象
- 递归示例:斐波那契数列
// 首先进行数学抽象,明确该函数返回值的意义 // 该函数返回值是斐波那契数列中第i个位置的值 // 根据斐波那契数列的数学规律,我们知道第i个位置的值等于其前两个位置值之和,即fibonacci(i-1)+fibonacci(i-2) // 当处于第一或第二个位置时,由于其前面不足两个元素,因此要单独考虑 func fibonacci(i int)int{ if i <= 2{ return 1 } return fibonacci(i-1)+fibonacci(i-2) } func main(){ for i:=1;i<=10;i++{ fmt.Printf("%v ",fibonacci(i)) // 输出:1 1 2 3 5 8 13 21 34 55 } fmt.Println("") }
三、练习
1.构造一个闭包,输入文件名时,为其添加相应后缀,如输入文件名"hello",输出"hello.jpg"
func addSuffix(suffix string)func(name string)string{
return func(name string)string{
if strings.HasSuffix(name,suffix){
return name // 如果名字中自带了该后缀,则无需添加
}
return name+suffix // suffix不是该函数内的变量,相当于使用了外部变量,延长其生命周期
}
}
func main(){
addJpg := addSuffix(".jpg") // 返回值是一个func(string)string类型函数,其保存了外部变量suffix的值为:".jpg"
addPng := addSuffix(".png") // 返回值是一个func(string)string类型函数,其保存了外部变量suffix的值为:".png"
fmt.Println(addJpg("Hello")) // 输出: Hello.jpg
fmt.Println(addPng("Go")) // 输出: Go.png
}
2.使用递归实现爬楼梯:即某人一次只能爬1级或2级阶梯,当输入阶梯数量i时,要求输出一共有多少种走法去爬楼梯。
- 首先对问题进行抽象,明确函数的返回值是什么
- 根据题目可知,函数的返回值为i层阶梯共有多少种走法
- 接下来考虑我们第一步如何走
- 如果我们第一步只走一级,那剩下i-1级阶梯,共有climb(i-1)种走法
- 如果我们第一步走2级阶梯,那剩下i-2级阶梯,共有climb(i-2)中走法
- 所以i层阶梯我们一共可以有climb(i-1)+climb(i-2)种走法
- 最后考虑特殊情况,如果阶梯只有一级,那只有一种走法,阶梯有2级,只有两种走法。
- 代码实现如下
func climb(i int)int{ if i == 1 || i == 2{ //如果只有1级阶梯,只有一种走法,2级阶梯,只有2种走法 return i } return climb(i-1)+climb(i-2) // climb(i-1)表示走了1级阶梯后还有多少种走法,climb(i-2)表示走了(i-2)级阶梯后还有多少走法 } func main(){ fmt.Println(climb(5)) // 输出8 }
总结
Go语言中函数通过关键字func声明,参数列表和返回值列表都可以有0个或多个元素。函数的类型包括其参数列表和返回值列表。当某些功能仅在特定场合下使用时,可使用匿名函数。当函数作为参数时,称之为回调函数。当函数作为返回值时,称为闭包。函数在实现时调用自身,称为递归。