Go语言学习——函数二 defer语句

函数

package main

import "fmt"

// 函数:一段代码的封装

func f1(){
	fmt.Println("Hello 中国!")
}

func f2(name string) {
	fmt.Println("Hello", name)
}

// 带参数和返回值的函数
func f3(x int, y int) int {
	sum := x + y
	return sum
}

// 参数类型简写
func f4(x, y int) int {
	return x + y
}

// 可变参数
func f5(title string, y ...int) int {
	fmt.Println(y) // y是一个int类型的切片
	return 1
}

// 命名返回值
func f6(x, y int) (sum int) {
	sum = x + y // 如果使用命名的返回值,那么在函数中可以直接使用返回值变量
	return // 如果使用命名的返回值 return 后面可以省略返回值变量
}

// Go语言中支持多个返回值
func f7(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

func main () {
	f1()
	f2("理想")
	f2("梦想")
	f3(100, 200) // 调用函数
	fmt.Println(f3(100, 200))
	ret := f3(300, 400)
	fmt.Println(ret)

	f5("太阳", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
	// 在一个命名的函数中不能够再声明命名函数
	// func f8()  {
		
	// }
	
}

defer语句

defer语句会将其后面跟随的语句进行延迟处理

在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行

先被defer的语句最后被执行,最后被defer的语句,最先被执行

package main

import "fmt"

// defer

// defer多用于函数结束之前释放资源(文件句柄、数据库连接、socket连接)
func deferDemo(){
	fmt.Println("start")
	defer fmt.Println("hello") // defer把它后面的语句延迟到函数即将返回的时候再执行
	defer fmt.Println("apple") // 一个函数中可以有多个defer语句
	defer fmt.Println("banana") // 多个defer语句安装先进后出(后进先出)的顺序延迟执行
	fmt.Println("end")
}

func main(){
	deferDemo()
}

defer执行时机

return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步

defer语句执行的时机在返回值赋值操作后,RET指令执行前

package main

import "fmt"

// Go语言中函数的return不是原子操作,在底层分为两步来执行
// 第一步:返回值赋值
// defer
// 第二版:真正的RET返回
// 函数中如果存在defer,那么defer执行的时机是在第一步和第二步之间

func f1() int {
	x := 5
	defer func() {
		x++ // 修改的是x不是返回值
	}()
	return x
}

func f2() (x int) {
	defer func() {
		x++
	}()
	return 5 // 返回值=x
}

func f3() (y int) {
	x := 5
	defer func() {
		x++ // 修改的是x
	}()
	return x // 返回值=y=x=5
}
func f4() (x int) {
	defer func(x int) {
		x++ // 改变的是函数中的副本
	}(x)
	return 5 // 返回值=x=5
}
func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3())
	fmt.Println(f4())
}
posted @ 2022-05-07 22:46  寻月隐君  阅读(31)  评论(0编辑  收藏  举报