函数function
- Go函数不支持嵌套,重载和默认参数
- 但支持的特性:无需声明原型,不定长度变参,多返回值,命名返回值参数(遍历的做法),匿名函数,闭包
- 定义函数使用关键字func,且左大括号不能另起一行
- 函数也可以作为一种类型使用
函数的使用
func 函数名(传入值) (返回值) {}
func main() {
A(1, 2)
}
func A(a ...int) { //不定长变参的使用就是创建slice,使用时必须作为参数列表的最后一个参数
fmt.Println(a)
}
运行结果:
函数使用slice,是对slice的地址拷贝操作
func main() {
s1 := []int{1, 2, 3, 4}
A(s1)
fmt.Println(s1)
}
func A(s []int) {
s[0] = 5
s[1] = 6
s[2] = 7
s[3] = 8
fmt.Println(s)
}
运行结果:
传递值类型和引用类型
函数调用数组,仅仅是数值的拷贝是引用类型
func main() {
a := 1
A(a)
fmt.Println(a)
}
func A(a int) {
a = 2
fmt.Println(a)
}
运行结果:
函数可以通过指针,来调用修改值类型
func main() {
a := 1
A(&a)
fmt.Println(a)
}
func A(a *int) {
*a = 2
fmt.Println(*a)
}
运行结果:
函数类型的使用(Go语言中一切皆类型)
func main() {
a := A
a()
}
func A() {
fmt.Println("Func A")
}
运行结果:
匿名函数
匿名函数不可以作为顶级函数,只在别的函数体当中,不能当做最外层函数
func main() {
a := func() {
fmt.Println("Func B")
}
a()
}
运行结果:
闭包
func main() {
f := closure(10)
fmt.Println(f(1))
fmt.Println(f(2))
}
func closure(x int) func(int) int {
return func(y int) int {
return x + y
}
}
运行结果:
三次调用指向的x是同一个x
func main() {
f := closure(10)
fmt.Println(f(1))
fmt.Println(f(2))
}
func closure(x int) func(int) int {
fmt.Printf("%p\n", &x)
return func(y int) int {
fmt.Printf("%p\n", &x)
return x + y
}
}
运行结果:
defer
- 的执行方式类似其他语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
- 即使函数发生严重错误也会执行
- 支持匿名函数的调用
- 常用于资源清理,文件关闭,解锁以及记录时间等操作
- 通过与匿名函数配合可在return之后修改函数计算结果
- 如果函数体内某个变量作为defer时匿名函数的参数,则定义defer时已经获得了拷贝,否则则是引用某个变量的地址
- Go没有异常机制,但有painc/recover模式来处理错误
- Painc可以在任何地方引发,但recover只有在defer调用的函数中有效
后定义的先调用
func main() {
fmt.Println("a")
defer fmt.Println("b")
defer fmt.Println("c")
defer fmt.Println("d")
}
运行结果:
func main() {
for i := 0; i < 3; i++ {
fmt.Println(i)
}
}
运行结果:
放到匿名函数中,闭包时
func main() {
for i := 0; i < 3; i++ {
defer func() {
fmt.Println(i)
}() //调用这个函数相当于 defer a()
}
}
运行结果:
painc与recover
程序陷入panic状态
func main() {
A()
B()
C()
}
func A() {
fmt.Println("Func A")
}
func B() {
panic("painc in B")
}
func C() {
fmt.Println("Func C")
}
运行结果:
通过defer把程序从panic状态recover回到正常状态。然后painc不再执行
painc会使程序直接中断运行,需要把defer放在painc之前
func main() {
A()
B()
C()
}
func A() {
fmt.Println("Func A")
}
func B() {
defer func() {
//通过defer把程序从panic状态recover回到正常状态。然后painc不再执行
if err := recover(); err != nil {
fmt.Println("Recover in B")
}
}()
panic("painc in B")
}
func C() {
fmt.Println("Func C")
}
运行结果:
func main() {
var fs = [4]func(){}
for i := 0; i < 4; i++ {
defer fmt.Println("defer i = ", i)
defer func() { fmt.Println("defer_closure i =", i) }()
fs[i] = func() { fmt.Println("closure i = ", i) }
}
for _, f := range fs {
f()
}
}
运行结果: