本章介绍函数的定义和用法
- 函数支持0个或者多个参数
- 函数支持0个或者多个返回值
1. 基本函数定义
语法:
func 函数名(参数列表) (返回值类型列表) {
}
例子:
package main
import "fmt"
// 定义add函数,接受两个int参数,返回值是int类型
func add(x int, y int) int {
return x + y
}
func main() {
// 调用函数add, 然后调用Println函数打印返回值
fmt.Println(add(42, 13))
}
2. 返回多个值的函数
go语言的函数允许返回多个值
例子:
package main
import "fmt"
// 定义swap函数,接受x,y两个参数,swap函数的作用是交换两个参数值
// 连续多个参数的类型一致的话,可以用逗号分隔变量,仅在最后一个变量书写数据类型
// 返回两个string类型的值
func swap(x, y string) (string, string) {
// 返回多个值,用逗号分隔
return y, x
}
func main() {
// 调用swap函数,并且接受两个返回值,按顺序传递给a和b变量
a, b := swap("hello", "world")
fmt.Println(a, b)
}
3. 返回命名参数值
我们可以给函数返回值定义命名参数。
例子:
package main
import "fmt"
// 定义split函数
// 定义x,y两个int类型的返回值参数
func split(sum int) (x, y int) {
// 给x返回值参数赋值
x = sum * 4 / 9
// 给y返回值参数赋值
y = sum - x
// 直接return,就可以返回x,y参数值
return
}
func main() {
fmt.Println(split(17))
}
4.忽略参数返回值
函数可以返回多个值,有时候我们只想要其中一个值,可以通过 _ 下划线符号,忽略返回值。
接上面的例子
// 忽略掉第一个返回值,接受第二个返回值
_, y := split(17)
// 接受第一个返回值,忽略第二个返回值
x, _ := split(17)
4. defer语句
defer是延迟调用语句,延迟调用指的是被defer修饰的函数调用,在父函数执行接结束的时候才会执行defer修饰的函数。
4.1. 基本用法
例子:
package main
import "fmt"
func main() { // 父函数
// 延迟调用Println函数,也就是延迟打印world字符串
defer fmt.Println("world")
// 打印hello
fmt.Println("hello")
}
执行代码输出:helloworld
执行流程说明:
使用defer修饰fmt.Println("world"),并不会立即执行Println函数,所以不会打印world。
fmt.Println("hello")语句会立即执行,输出hello
这个时候main函数执行结束,因为main函数是父函数,这个时候会执行 defer fmt.Println("world") 函数,输出world。
说明:父函数是一个相对概念,调用函数的函数,就是父函数。
4.2. defer调用栈
如果在同一个函数中,存在多个defer修饰的延迟调用函数,那么执行顺序是怎么样的?
例子:
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
// 延迟打印 i
defer fmt.Println(i)
}
// 会比上面的defer语句先执行
fmt.Println("done")
}
执行后输出:
counting
done
9
8
7
6
5
4
3
2
1
0
执行流程,延迟调用函数,会保存在一个调用栈中,执行的时候反序执行,所以看到上面例子,数字倒序输出。
5.闭包(匿名函数)
没有函数名的函数,我们叫做匿名函数,通常也叫做闭包,它拥有可以引用定义闭包上下文环境变量的特性。
简单的闭包例子:
// 定义一个闭包,并将闭包函数赋值给变量f
f := func() {
fmt.Println("我是闭包函数")
}
// 通过变量f调用闭包函数
f();
闭包引用上下文环境变量的例子:
package main
import (
"fmt"
)
func main() {
// 计数器变量
count := 0
// 定义一个闭包,并将闭包函数赋值给变量f
f := func() {
// 因为闭包函数是在main函数中定义的,所以可以引用main函数定义的变量
count++
fmt.Println("count=", count)
}
// 通过变量f调用闭包函数
f();
f();
f();
}
输出:
count= 1
count= 2
count= 3
上下文环境,指的就是定义闭包函数的函数内的局部作用域。