golang-defer关键字笔记

本文详细探讨了Go语言中`defer`关键字的使用,包括其执行顺序(后进先出)以及如何影响函数返回值。通过实例展示了`defer`的拷贝特性,解释了为何在函数返回时,`defer`内部的变量值可能与预期不符。此外,还分析了`defer`与匿名和命名返回值的关联,揭示了它们如何影响返回结果。
摘要由CSDN通过智能技术生成

1.defer修饰的函数的执行顺序

例如:

package main

import "fmt"

func main() {

	defer func() {
		fmt.Println("world")
	}()

	defer func() {
		fmt.Println("hello")
	}()

	defer func() {
		fmt.Println("110")
	}()
}

运行结果:
110
hello
world

defer定义的函数的执行顺序跟栈的结构一样,先进后出的顺序执行对应的函数。实际使用中如果要严格的执行顺序,一定要格外注意。

2.defer的拷贝特性

示例:

package main

import "fmt"

func Show(n int) int {
	defer fmt.Println("defer n = ", n)
	n++
	return n
}

func Modify(str *string) {
	*str += " world"
	defer fmt.Println(*str)
	*str += " wula"
}
func main() {

	fmt.Println("Show n = ", Show(1))
	ss := "hello"
	Modify(&ss)
	fmt.Println(ss)
}

运行结果:
[root@localhost go]# go run godefer.go 
defer n =  1
Show n =  2
hello world
hello world wula

如上代码所示,按照defer关键字,在函数返回的时候才执行,按照正常的逻辑n应该为2,为什么结果等于1呢?是因为defer 函数,的时候,除了将对应的函数放到执行栈中,还将对应的使用的值进行了一份拷贝。等到执行时候,直接就输出了存放函数栈时的值。

3. defer跟return的返回关联

package main

import "fmt"

// 匿名返回
func Kan() int {
	var i int
	defer func() {
		i++
		fmt.Println("Kan >>>", i)
	}()

	defer func() {
		i++
		fmt.Println("Kan <<<", i)
	}()

	return i // 匿名返回函数该处底层会创建一个副本进行返回,类似t = i,在return之前执行defer函数,但是此时return处的值已经为t,在defer执行完之后,返回的就是t
}

// 命名返回
func Jan() (i int) {

	defer func() {
		i++
		fmt.Println("Jan >>>", i)
	}()

	defer func() {
		i++
		fmt.Println("Jan <<<", i)
	}()

	return i // 命名返回该处不会创建副本,仍旧i本身,实际在return之前,就已经调用了defer函数,从而导致i的值被修改了,故此可称为defer修改命名返回函数的值
}

func main() {
	fmt.Println(Kan())
	fmt.Println(Jan())
}


运行结果:
[root@localhost go]# go run godefer.go 
Kan <<< 1
Kan >>> 2
0
Jan <<< 1
Jan >>> 2
2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值