写点什么

Go 语言入门 08—函数

作者:良猿
  • 2022-10-27
    湖北
  • 本文字数:2130 字

    阅读完需:约 7 分钟

Go语言入门08—函数

函数

函数是 go 语言中最基础的代码块,通常将需要当做一个整体执行的任务抽象成一个函数,例如前面用到的 len、cap 和 append 等都是系统定义好的函数,还有 go 里面的 main 函数,他是 go 程序运行的入口函数,是必不可少的一个主函数,而且 go 语言中有且仅有一个 main 主函数。

函数声明

函数声明时需要指定函数名称、参数列表和返回列表。


声明函数时需要使用关键字 func,函数声明语法如下:


func 函数名( 参数列表 ) (返回列表) {   // 函数体}
复制代码


函数名:在其他地方调用时需要用到的名称


参数列表:当函数被调用时可以根据参数列表传递对应的参数,在函数体中可以使用参数,参数列表需要指定参数名和参数类型,参数个数是可选的,可以没有参数也可以有多个参数。


返回列表:当函数执行完成之后返回的数据,返回列表需要指定返回类型,返回列表可选,可以没有返回值,也可以有多个返回值。


函数体:函数核心,需要执行的代码逻辑。


代码示例:


package main
import "fmt"
func main() { result := add(1,2) fmt.Println(result)}
// 声明一个函数,传入两个int类型整数,返回两个数相加的和func add(n1 int, n2 int) int { return n1 + n2}
复制代码


如上定义了一个函数 add,返回两数之和,当两个参数的类型一样时,还可以写成这样func add(n1, n2 int),在 main 函数中调用该函数传入两个整数,返回的 result 结果为 3。


在 go 语言中,函数可以有多个返回值。


代码示例:


package main
import "fmt"
func main() { add, sub := addAndSub(1,2) fmt.Println(add) fmt.Println(sub)}
// 声明一个函数,传入两个int类型整数,返回两个结果,一个是两数之和,一个是两数之差func addAndSub(n1 int, n2 int) (add int, sub int) { add = n1 + n2 sub = n1 - n2 return add, sub}
复制代码


如上所示,声明一个函数 addAndSub,该函数有两个返回值,一个是两数之和,一个是两数之差,当有多个返回值时,返回值列表写法可以和参数列表写法一致,在返回值列表中声明了的返回值明,在函数体中可以直接使用,例如变量 add 和 sub 在函数体中可以不用重新声明,直接使用即可,返回列表同样还可以只写返回类型,不写具体的变量名,例如func addAndSub(n1 int, n2 int) (int,int),表示返回两个整形。


运行结果:


函数调用

函数调用很好理解,例如上面的 addAndSub 函数,在 main 函数中调用时直接写函数名即可,需要注意以下几点:


  1. 如果函数有多个参数,则在调用函数传参数时需要注意参数个数和顺序,以及参数类型。

  2. 如果函数有多个返回值,则同样需要以多个变量接收,多个变量之间用逗号隔开,同样也可以只接收其中部分返回值,忽略其他返回值,例如add, _ := addAndSub(1,2),表示只接收和的返回值,忽略差的返回值。

值传递和引用传递

在函数中,传参最重要的部分就是值传递和引用传递。


  • 值传递:在调用函数时,将实际参数拷贝一份传递到函数中,在函数中对参数的改变不会影响到实际的参数。

  • 引用传递:在调用函数时,将实际参数的地址传递到函数中,在函数中对参数的操作会影响到实际的参数。


值传递示例:


package main
import "fmt"
func main() { // 定义局部变量 num := 1 fmt.Println("改变前num的值:", num) // 将实际参数传递给函数change change(num) fmt.Println("改变后num的值:", num)}
// 定义一个函数,将传递进来的参数的值变为10func change(num int) { num = 10}
复制代码


运行结果:



由上可见,由于函数 change 是值传递,所以在函数内部对参数的改变并不会影响到实际参数,而且在 go 语言中默认使用的就是值传递。


引用传递示例:


package main
import "fmt"
func main() { // 定义局部变量 num := 1 fmt.Println("改变前num的值:", num) // 将实际参数传递给函数change change(&num) fmt.Println("改变后num的值:", num)}
// 定义一个函数,将传递进来的参数的值变为10func change(num *int) { *num = 10}
复制代码


运行结果:



当使用引用传递时,函数的参数类型为*int,在 main 函数中调用该函数时,传递的是实际参数在内存中的存放地址,因此在 change 函数中对参数的改变会影响到实际参数。

延迟调用

在 go 语言函数中,可以对函数进行延迟调用,延迟调用需要使用到defer关键字,在函数调用前面加上该关键字,则该函数不会立即被调用,而是会延迟调用。


代码示例:


package main
import "fmt"
func main() { defer delay() fmt.Println("主函数执行...")}
func delay() { fmt.Println("延迟调用...")}
复制代码


运行结果:



如上所示,定义了一个函数delay,虽然该函数在 main 主函数中的第一行就被调用了,但是该函数中的打印却是在主函数打印出主函数执行后才进行打印,这就是延迟调用,延迟调用会等待主函数都执行完成之后再执行。


如果一个主函数中同时有多个延迟调用,那么最后的执行顺序会按照代码的顺序逆序执行。例如以下代码:


defer delay1()defer delay2()defer delay3()
复制代码


这三个延迟调用函数,在主函数执行完成之后,会按照delay3delay2delay1的顺序执行。


延迟调用可以用于数据库连接关闭函数,在连接数据库之后立马延迟调用数据库连接关闭函数,这样数据库连接不会立马被关闭,而且也不会导致写完代码之后忘记关闭数据库连接。


发布于: 刚刚阅读数: 3
用户头像

良猿

关注

还未添加个人签名 2019-02-13 加入

还未添加个人简介

评论

发布
暂无评论
Go语言入门08—函数_Go_良猿_InfoQ写作社区