1 函数
函数是go语言中最基础的代码块,通常将需要当做一个整体执行的任务抽象成一个函数,例如前面用到的len、cap和append等都是系统定义好的函数,还有go里面的main函数,他是go程序运行的入口函数,是必不可少的一个主函数,而且go语言中有且仅有一个main主函数。
2 函数声明
函数声明时需要指定函数名称、参数列表和返回列表。
声明函数时需要使用关键字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)
,表示返回两个整形。
运行结果:
3 函数调用
函数调用很好理解,例如上面的addAndSub函数,在main函数中调用时直接写函数名即可,需要注意以下几点:
- 如果函数有多个参数,则在调用函数传参数时需要注意参数个数和顺序,以及参数类型。
- 如果函数有多个返回值,则同样需要以多个变量接收,多个变量之间用逗号隔开,同样也可以只接收其中部分返回值,忽略其他返回值,例如
add, _ := addAndSub(1,2)
,表示只接收和的返回值,忽略差的返回值。
4 值传递和引用传递
在函数中,传参最重要的部分就是值传递和引用传递。
- 值传递:在调用函数时,将实际参数拷贝一份传递到函数中,在函数中对参数的改变不会影响到实际的参数。
- 引用传递:在调用函数时,将实际参数的地址传递到函数中,在函数中对参数的操作会影响到实际的参数。
值传递示例:
package main
import "fmt"
func main() {
// 定义局部变量
num := 1
fmt.Println("改变前num的值:", num)
// 将实际参数传递给函数change
change(num)
fmt.Println("改变后num的值:", num)
}
// 定义一个函数,将传递进来的参数的值变为10
func 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)
}
// 定义一个函数,将传递进来的参数的值变为10
func change(num *int) {
*num = 10
}
运行结果:
当使用引用传递时,函数的参数类型为*int
,在main函数中调用该函数时,传递的是实际参数在内存中的存放地址,因此在change函数中对参数的改变会影响到实际参数。
5 延迟调用
在go语言函数中,可以对函数进行延迟调用,延迟调用需要使用到defer
关键字,在函数调用前面加上该关键字,则该函数不会立即被调用,而是会延迟调用。
代码示例:
package main
import "fmt"
func main() {
defer delay()
fmt.Println("主函数执行...")
}
func delay() {
fmt.Println("延迟调用...")
}
运行结果:
如上所示,定义了一个函数delay
,虽然该函数在main主函数中的第一行就被调用了,但是该函数中的打印却是在主函数打印出主函数执行
后才进行打印,这就是延迟调用,延迟调用会等待主函数都执行完成之后再执行。
如果一个主函数中同时有多个延迟调用,那么最后的执行顺序会按照代码的顺序逆序执行。 例如以下代码:
defer delay1()
defer delay2()
defer delay3()
这三个延迟调用函数,在主函数执行完成之后,会按照delay3
,delay2
,delay1
的顺序执行。
延迟调用可以用于数据库连接关闭函数,在连接数据库之后立马延迟调用数据库连接关闭函数,这样数据库连接不会立马被关闭,而且也不会导致写完代码之后忘记关闭数据库连接。
本文参与了SegmentFault 思否写作挑战赛活动,欢迎正在阅读的你也加入。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。