函数function
-
Go函数不支持嵌套、重载和默认参数
-
但是支持以下特性
-
- 无需声明函数原型(C\C++需要)
-
- 不定长度变量参数
-
- 多返回值
-
- 命名返回值参数
-
- 匿名函数
-
- 闭包
-
定义函数使用关键字func,且左大括号不能另起一行
-
函数也可以作为一种类型使用
函数基本写法
func func01() {
fmt.Println("package lesson file lesson/lesson09.go function func01")
}
一般的函数参数
func func02(a int, b string) {
fmt.Println("package lesson file lesson/lesson09.go function func02")
fmt.Println("func get value [a]:", a, " [b]:", b)
}
函数参数省略写法
func func03(a, b, c int) {
fmt.Println("package lesson file lesson/lesson09.go function func03")
fmt.Println("func get value [a]:", a, " [b]:", b, " [c]:", c)
}
多返回值 - 建议使用这种
func func04() (int, int, int) {
fmt.Println("package lesson file lesson/lesson09.go function func04")
a, b, c := 1, 2, 3
return a, b, c
}
多返回值省略写法
func func05() (a, b, c int) {
fmt.Println("package lesson file lesson/lesson09.go function func05")
a, b, c = 1, 2, 3
return
}
不定长度变量参数
func func06(a ...int) {
fmt.Println("package lesson file lesson/lesson09.go function func06")
fmt.Println("[a]:", a, " [a.type]:", reflect.TypeOf(a))
}
固定变量与不定长度变量参数混合使用
func func07(b string, a ...int) {
fmt.Println("package lesson file lesson/lesson09.go function func07")
fmt.Println("[b]:", b, " [a]:", a, " [a.type]:", reflect.TypeOf(a))
}
不定长度变量的函数,不会对外发生变更
func func08(slice ...int) {
fmt.Println("package lesson file lesson/lesson09.go function func08")
fmt.Println("[slice]:", slice)
slice[0] = 3
slice[1] = 4
fmt.Println("[slice]:", slice)
}
定常Slice作为变量传入函数
// 定常的slice作为变量传入函数,会造成外部的slice发生变更
// 这种方式进行的拷贝是slice当中地址的拷贝,也就是说操作其中的数据直接产生影响
func func09(slice []int) {
fmt.Println("package lesson file lesson/lesson09.go function func09")
fmt.Println("[func09.slice]:", slice)
slice[0] = 3
slice[1] = 4
fmt.Println("[func09.slice]:", slice)
}
引用类型的传递
func func10(a *int) {
fmt.Println("package lesson file lesson/lesson09.go function func10")
*a = 2
fmt.Println("[a.address]:", a, "[a.value]:", *a)
}
函数名称作为变量
fmt.Println()
fmt.Println("test func11")
function01 := func01
function01()
匿名函数
fmt.Println()
fmt.Println("test func12")
function02 := func() {
fmt.Println("package lesson file lesson/lesson09.go function Anonymous Function ")
}
function02()
闭包
func closure(x int) func(int) int {
fmt.Println("[&x]:", &x)
return func(y int) int {
fmt.Println("[&x]:", &x)
return x + y
}
}
闭包调用
// 闭包
fmt.Println()
function03 := closure(10)
fmt.Println(function03(1))
fmt.Println(function03(2))
defer
- defer的执行方式类似其他预演中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
- 即使函数发生严重错误也会执行
- 支持匿名函数的调用
- 常用语资源清理、文件关闭、解锁一级记录时间等操作
- 通过与匿名函数配合可在return之后修改函数计算结果
- 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址
defer倒序打印
func func11(){
fmt.Println("a")
defer fmt.Println("b")
defer fmt.Println("c")
}
打印输出
a
c
b
循环中使用defer
for index:=0; index < 3;index++ {
defer fmt.Println("[index]:",index)
}
输出
2,1,0
循环中对函数使用defer
这里实际是闭包,在func里面的index是引用,但是由于defer是在循环的最后进行引用,
for index := 0;index < 3;index++{
defer func() {
fmt.Println("[index]:",index)
}() // 调用这个函数
}
输出
3,3,3
panic/recover
panic/recover 可以理解为try catch
- Go没有异常机制,但是panic/recover模式来处理错误
- Panic可以在任何地方引发,但recover只有在defer调用的函数中有效
func defer04() {
fmt.Println()
fmt.Println("package lesson file lesson/lesson09.go function defer04")
functionPrintA()
functionPanicB()
functionPrintC()
}
func functionPrintA() {
fmt.Println("package lesson file lesson/lesson09.go function functionPrintA")
}
func functionPanicB() {
// 在panic之前设置defer函数,才能够让defer被访问到
defer func() {
if err := recover(); err != nil {
fmt.Println("Recover in B")
}
}()
panic("package lesson file lesson/lesson09.go panic functionPanicB")
}
func functionPrintC() {
fmt.Println("package lesson file lesson/lesson09.go function functionPrintC")
}
程序输出
package lesson file lesson/lesson09.go function defer04
package lesson file lesson/lesson09.go function functionPrintA
Recover in B
package lesson file lesson/lesson09.go function functionPrintC
程序首先运行panic,出现故障,此时跳转到包含recover()的defer函数执行,recover捕获panic,此时panic就不继续传递.但是recover之后,程序并不会返回到panic那个点继续执行以后的动作,而是在recover这个点继续执行以后的动作,即执行上面的defer函数,输出1
课堂作业
分析以下程序输出结果
func homework() {
fmt.Println("package lesson file lesson/lesson09.go function homework")
var fs = [4]func(){}
for index := 0; index < 4; index++ {
defer fmt.Println("defer [index]:", index)
defer func() {
fmt.Println("defer_closure [index]:", index)
}()
fs[index] = func() {
fmt.Println("closure [index]:", index)
}
}
for _, f := range fs {
f()
}
}
输出结果
package lesson file lesson/lesson09.go function homework
closure [index]: 4
closure [index]: 4
closure [index]: 4
closure [index]: 4
defer_closure [index]: 4
defer [index]: 3
defer_closure [index]: 4
defer [index]: 2
defer_closure [index]: 4
defer [index]: 1
defer_closure [index]: 4
defer [index]: 0