[08]Golang的函数体function

函数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()
	}
}

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值