函数
在Go语言中,函数可以分为具名函数和匿名函数,包级函数一般是具名函数,具名函数是匿名函数的一种特例。函数也可以看成是封装好一系列语句的代码块,用以提高代码的模块度和复用率。
Go语言的函数属于“一等值,(first-class)”,满足以下特点:
- 函数本身可以被当成值传递
- 函数本身可以满足接口
- 支持匿名函数和闭包
函数调用
需求:定义两个函数,实现两数相加和两数相乘的功能,允许被main函数外部调用。
//定义一个小马函数实现两数相加功能func Xiaoma(a int,b int)int{ sum := a + b fmt.Println("小马a+b:",sum) return sum //当有返回值语句时,谁调用就返回给谁}//定义一个佳豪函数实现两数相乘功能func Jiahao(a int,b int) { //没有返回值 b += 1 sumAdd := a * b fmt.Println("佳豪a*b:",sumAdd)}func main(){ a := 2 b := 3 //打印初始值 fmt.Printf("a = %d\n",a) fmt.Printf("b = %d\n",b) //调用小马 sum := Xiaoma(a,b) //传参 fmt.Println("a+b:", sum) //接受返回值 //调用佳豪 Jiahao(a,b) //传参 fmt.Println("a*b:", a*b)}/*a = 2b = 3小马a+b: 5a+b: 5佳豪a*b: 8a*b: 6*/
可以说明,当一个函数具有返回值时,就将返回值返回给调用的函数。例如,Xiaoma函数的返回值是5,返回值“原路返回”以后,主函数就接收到了返回值sum,最后打印输出sum,为5;当一个函数没有返回值时,就什么都不做。例如,Jiahao函数没有返回值,函数顺序执行,先打印Jiahao函数体的输出 ab =8,接着再打印主函数的 a b =6。
调用机制
(此处用Process.com画一个图)
根据上述代码块可以得知Go语言的函数调用具有以下特点
- 在调用函数时,内存会为该函数分配一个栈空间,编译器会让不同函数之间都能区分开来。
- 在每个函数对应的栈空间中,数据空间是独立的,不会混淆
- 当函数调用执行完毕后,程序会回收函数所在的栈空间,释放内存资源
- 如果有返回值语句,就将返回值返回给调用的函数(语句);如果没有返回值,就什么都不做
返回值的声明形式
返回值就是函数执行后返回的内容,Go语言的函数允许有单个、多个甚至是没有返回值。
- 如果函数有返回值,必须要在函数最后添加 return 语句;如果函数没有返回值,那么就省略最后的返回信息,什么都不用写。
如果函数只有一个返回值,且不声明返回值变量,那么可以省略这个返回值不写
func max (a,b int)(maxNum int){//形参列表a和b都是int型,可以合并;返回值只有一个maxNum,且 if a > b { return a } return b}
如果函数是多返回值函数,如果不声明变量,也要指定其返回值类型。(以下两种声明方式等价)
//声明多返回值类型时形参类型一样可以合并,需要指定其返回值类型,可以省略变量func Cat (A, B int)(int, int){ return A + b, A * B }//另外一种多返回值函数的声明形式,指定返回值变量及其类型func Cat(A, B int)(Sum int, SumAdd int){ Sum := A + B SumAdd := A * B return Sum, SumAdd}
【注】:私有函数名一般使用小写开头,公有函数名一般使用大写开头。两者之间的区别在于是否能被外部调用。
多返回值函数调用
需求:定义一个可以实现四则运算的函数,拥有多个返回值,允许被main函数外部调用
//定义一个能够求矩形周长和面积的函数func Rectangle(a, b int)(d int,s int){ d := 2*(a+b) s := a*b return d, s //返回值}//主函数func main (){ a := 3 b := 4 dog, cat := Rectangle(a,b) //传参 //打印初始值 fmt.Println("a的初始值:",a) fmt.Println("b的初始值:",b) //打印结果 fmt.Printf("矩形周长%d\n", dog) fmt.Printf("矩形面积%d\n", cat)}/*a的初始值: 3b的初始值: 4矩形周长14矩形面积12*/
但是,多返回值也意味着有时候并不是全部都需要,我们可以使用空标识符 "_" 忽略函数返回值。还是以上面的代码为例,只需要 Rectangle 函数实现求周长的功能,不需要求出面积。
//只需要 Rectangle 函数实现求周长的功能,不需要求出面积func Rectangle(a, b int)(int, int){ d := 2*(a+b) s := a*b return d, s }//主函数func main (){ a := 3 b := 4 dog, _ := Rectangle(a, b) //将第一个返回值d赋值给dog, 返回值s赋值给空标识符, 然后自动丢弃 //打印初始值 fmt.Println("a的初始值:",a) fmt.Println("b的初始值:",b) //打印结果 fmt.Printf("矩形周长%d\n", dog) //fmt.Printf("矩形面积%d\n", cat) //编译报错,因为cat参数已被忽略}/*a的初始值: 3b的初始值: 4矩形周长14*/
函数作为参数
刚刚在本文前言已经提到了,函数作为“一等值”,是可以作为参数传递的,然后可以在其他函数内部调用执行,称为“回调”。只要求被调用函数的返回值个数、返回值类型、返回值顺序与调用函数所需的实参是一致的,就可以把这个被调用的函数当作其他函数的参数。
(代码待补充,暂时理解不了)
函数作为类型
(施工中)
可变参数
(施工中)
匿名函数与闭包
匿名函数是指不需要定义函数名的一种函数定义方式。当一个函数声明没有命名函数名称时,不能够独立存在;但可以被赋值于某个变量,即保存函数的地址到变量中。
package mainimport "fmt"func main() { f() //调用匿名函数}func f() { for i := 0; i < 4; i++ { g := func(i int) { fmt.Printf("%d ", i) //循环打印 } g(i) // fmt.Printf(" - g is of type %T and has value %v\n", g, g) }}/*0 - g is of type func(int) and has value 0x49c2201 - g is of type func(int) and has value 0x49c2202 - g is of type func(int) and has value 0x49c2203 - g is of type func(int) and has value 0x49c220*/
文章来源:智云一二三科技
文章标题:Golang 学习笔记:函数
文章地址:https://www.zhihuclub.com/3265.shtml