一文详解go的defer和return的执行顺序

 更新时间:2024年07月12日 08:40:35   作者:刘小帅574  
go的defer和return是golang中的两个关键字,return用于返回函数的返回值,也可以参与一定的流程控制,defer是golang中的延迟调用,经常用于文件流的关闭,锁的解锁操作,本文给大家介绍了go的defer和return的执行顺序,需要的朋友可以参考下

详解go的defer和return的执行顺序

go的defer和return是golang中的两个关键字,return用于返回函数的返回值,也可以参与一定的流程控制,比如下面代码,return短路了后面的输出

package main

import "fmt"

// defer 和 return的详解
func main() {
	foo(2)
	foo(1)
}
func foo(i int) {
	fmt.Println(i)
	if i == 1 {
		return
	}
	fmt.Println(i + 1)
}

结果:

2
3
1

第一次输出完整的输出了i和i+1,第二次输出被短路,只输出了1

defer是golang中的延迟调用,经常用于文件流的关闭,锁的解锁操作,defer后面的操作会在当前函数或者goroutine结束之后进行调用

package main

import "fmt"

// defer 和 return的详解
func main() {
	foo()
}
func foo() {
	defer fmt.Println("println defer")
	fmt.Println("println foo")
}

输出:
println foo
println defer

defer自身有一些特性,比如defer和defer之间的执行顺序是先进后出,先defer的最后执行,分析下面代码:

package main

import "fmt"

// defer 和 return的详解
func main() {
	foo()
}
func foo() {
	defer fmt.Println("floor 3")
	defer fmt.Println("floor 2")
	fmt.Println("floor 1")
}

输出:
floor 1
floor 2
floor 3

根据这一特性,如果我们defer调用的代码中存在panic 的可能性,为了保证系统的运行,我们应该在前面recover而不是后面

ackage main

import "fmt"

// defer 和 return的详解
func main() {
	foo()
}
func foo() {
	defer func() {
		panic("panic test")
	}()
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("catch panic:", err)
		}
	}()
}

输出:
panic: panic test
package main

import "fmt"

// defer 和 return的详解
func main() {
	foo()
}
func foo() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("catch panic:", err)
		}
	}()
	defer func() {
		panic("panic test")
	}()
}
输出:
catch panic: panic test

defer和return的相互影响

defer和return的相互影响,主要是在返回值上表现,考虑下面代码,输出应该是什么:

import "fmt"

// defer 和 return的详解
func main() {
	fmt.Println(foo1())
	fmt.Println(foo2())
	fmt.Println(foo3())
}
func foo1() int {
	i := 1
	defer func() { i++ }()
	return i
}
func foo2() (i int) {
	i = 1
	defer func() { i++ }()
	return i
}
func foo3() (i int) {
	defer func() { i++ }()
	return 1
}

输出:

1
2
2

导致上面情况的原因是

在 foo1 函数中,defer 语句中的闭包会在函数返回后执行,但是此时返回值已经确定为 1 ,所以最终返回 1 。

在 foo2 函数中,使用了命名返回值 i 。defer 语句中的闭包修改的是这个命名返回值,所以返回 2 。

在 foo3 函数中,同样使用了命名返回值 i ,defer 语句中的闭包修改了这个命名返回值,并且函数直接返回 1 ,但 defer 中的修改使得最终返回 2 。

而return的另一个特性,也会影响return和defer中代码的执行顺序

package main

import "fmt"

// defer 和 return的详解
func main() {
	fmt.Println(foo1())

}
func foo1() int {
	defer func() { fmt.Println("This is defer") }()
	return func() int {
		fmt.Println("This is return")
		return 1
	}()
}

输出:
This is return
This is defer
1

导致上面输出的原因是,return是非原子性的,defer会在return返回值之前执行,但return中的语句,会被全部执行,直到return锚定了某个值或者命名返回值,然后执行defer语句,最后返回return锚定的这个值

到此这篇关于一文详解go的defer和return的执行顺序的文章就介绍到这了,更多相关go defer和return执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang 1.16 中 Modules的主要变化更新

    Golang 1.16 中 Modules的主要变化更新

    这篇文章主要介绍了Golang 1.16 中 Modules的主要变化更新,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Go语言标准库之strconv的使用

    Go语言标准库之strconv的使用

    本文主要介绍了Go语言标准库之strconv的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • GoLang中的加密方法小结

    GoLang中的加密方法小结

    这篇文章主要介绍了GoLang中的加密方法。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • golang gorm中格式化时间问题详解

    golang gorm中格式化时间问题详解

    这篇文章主要给大家介绍了关于golang gorm中格式化时间问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • golang利用不到20行代码实现路由调度详解

    golang利用不到20行代码实现路由调度详解

    这篇文章主要给大家介绍了关于golang利用不到20行代码实现路由调度的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • 深入探究Golang中flag标准库的使用

    深入探究Golang中flag标准库的使用

    在本文中,我们将深入探讨 flag 标准库的实现原理和使用技巧,以帮助读者更好地理解和掌握该库的使用方法,文中的示例代码讲解详细,感兴趣的可以了解一下
    2023-04-04
  • go 语言爬虫库goquery的具体使用

    go 语言爬虫库goquery的具体使用

    GoQuery是专为Go语言设计的一个强大的HTML解析和查询库,本文主要介绍了go语言爬虫库goquery的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • 一文详解go中如何实现定时任务

    一文详解go中如何实现定时任务

    定时任务是指按照预定的时间间隔或特定时间点自动执行的计划任务或操作,这篇文章主要为大家详细介绍了go中是如何实现定时任务的,感兴趣的可以了解下
    2023-11-11
  • Go语言通过Luhn算法验证信用卡卡号是否有效的方法

    Go语言通过Luhn算法验证信用卡卡号是否有效的方法

    这篇文章主要介绍了Go语言通过Luhn算法验证信用卡卡号是否有效的方法,实例分析了Luhn算法的原理与验证卡号的使用技巧,需要的朋友可以参考下
    2015-03-03
  • 分享6个Go处理字符串的技巧小结

    分享6个Go处理字符串的技巧小结

    这篇文章主要介绍了分享6个Go处理字符串的技巧小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12

最新评论