博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go学习(14):defer
阅读量:4060 次
发布时间:2019-05-25

本文共 4179 字,大约阅读时间需要 13 分钟。

defer

1.1 延迟是什么?

即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语句返回。

1.2 延迟函数

你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题

  • 如果有很多调用defer,那么defer是采用后进先出模式
  • 在离开所在的方法时,执行(报错的时候也会执行)
func ReadWrite() bool {
file.Open("file") defer file.Close() if failureX {
return false } i f failureY {
return false } return true}

最后才执行file.Close()

示例代码:

package mainimport "fmt"func main() {
a := 1 b := 2 defer fmt.Println(b) fmt.Println(a)}

运行结果:

12

示例代码:

package mainimport (      "fmt")func finished() {
fmt.Println("Finished finding largest")}func largest(nums []int) {
defer finished() fmt.Println("Started finding largest") max := nums[0] for _, v := range nums {
if v > max {
max = v } } fmt.Println("Largest number in", nums, "is", max)}func main() {
nums := []int{
78, 109, 2, 563, 300} largest(nums)}

运行结果:

Started finding largest  Largest number in [78 109 2 563 300] is 563  Finished finding largest

1.3 延迟方法

延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。让我们编写一个小程序来测试这个。

示例代码:

package mainimport (      "fmt")type person struct {
firstName string lastName string}func (p person) fullName() {
fmt.Printf("%s %s",p.firstName,p.lastName)}func main() {
p := person {
firstName: "John", lastName: "Smith", } defer p.fullName() fmt.Printf("Welcome ") }

运行结果:

Welcome John Smith

1.4 延迟参数

延迟函数的参数在执行延迟语句时被执行,而不是在执行实际的函数调用时执行。

让我们通过一个例子来理解这个问题。

示例代码:

package mainimport (      "fmt")func printA(a int) {
fmt.Println("value of a in deferred function", a)}func main() {
a := 5 defer printA(a) a = 10 fmt.Println("value of a before deferred function call", a)}

运行结果:

value of a before deferred function call 10  value of a in deferred function 5

1.5 堆栈的推迟

当一个函数有多个延迟调用时,它们被添加到一个堆栈中,并在Last In First Out(LIFO)后进先出的顺序中执行。

我们将编写一个小程序,它使用一堆defers打印一个字符串。示例代码:

package mainimport (      "fmt")func main() {
name := "Naveen" fmt.Printf("Orignal String: %s\n", string(name)) fmt.Printf("Reversed String: ") for _, v := range []rune(name) {
defer fmt.Printf("%c", v) }}

运行结果:

Orignal String: Naveen  Reversed String: neevaN

1.6 延迟的应用

到目前为止,我们所写的示例代码,并没有实际的应用。现在我们看一下关于延迟的应用。在不考虑代码流的情况下,延迟被执行。让我们以一个使用WaitGroup的程序示例来理解这个问题。我们将首先编写程序而不使用延迟,然后我们将修改它以使用延迟,并理解延迟是多么有用。

示例代码:

package mainimport (      "fmt"    "sync")type rect struct {
length int width int}func (r rect) area(wg *sync.WaitGroup) {
if r.length < 0 {
fmt.Printf("rect %v's length should be greater than zero\n", r) wg.Done() return } if r.width < 0 {
fmt.Printf("rect %v's width should be greater than zero\n", r) wg.Done() return } area := r.length * r.width fmt.Printf("rect %v's area %d\n", r, area) wg.Done()}func main() {
var wg sync.WaitGroup r1 := rect{
-67, 89} r2 := rect{
5, -67} r3 := rect{
8, 9} rects := []rect{
r1, r2, r3} for _, v := range rects {
wg.Add(1) go v.area(&wg) } wg.Wait() fmt.Println("All go routines finished executing")}

修改以上代码:

package mainimport (      "fmt"    "sync")type rect struct {
length int width int}func (r rect) area(wg *sync.WaitGroup) {
defer wg.Done() if r.length < 0 {
fmt.Printf("rect %v's length should be greater than zero\n", r) return } if r.width < 0 {
fmt.Printf("rect %v's width should be greater than zero\n", r) return } area := r.length * r.width fmt.Printf("rect %v's area %d\n", r, area)}func main() {
var wg sync.WaitGroup r1 := rect{
-67, 89} r2 := rect{
5, -67} r3 := rect{
8, 9} rects := []rect{
r1, r2, r3} for _, v := range rects {
wg.Add(1) go v.area(&wg) } wg.Wait() fmt.Println("All go routines finished executing")}

程序运行结果:

rect {8 9}'s area 72  rect {-67 89}'s length should be greater than zero  rect {5 -67}'s width should be greater than zero  All go routines finished executing

转载地址:http://mmwji.baihongyu.com/

你可能感兴趣的文章
mongdb在java中的应用
查看>>
区块链技术让Yotta企业云盘为行政事业服务助力
查看>>
Yotta企业云盘更好的为媒体广告业服务
查看>>
Yotta企业云盘助力科技行业创高峰
查看>>
Yotta企业云盘更好地为教育行业服务
查看>>
Yotta企业云盘怎么帮助到能源化工行业
查看>>
企业云盘如何助力商业新发展
查看>>
医疗行业运用企业云盘可以带来什么样的提升
查看>>
媒体广告业如何将内容资产进行高效地综合管理与利用
查看>>
能源化工要怎么管控核心数据
查看>>
媒体广告业如何运用云盘提升效率
查看>>
企业如何运用企业云盘进行数字化转型-实现新发展
查看>>
司法如何运用电子智能化加快现代化建设
查看>>
iSecret&nbsp;1.1&nbsp;正在审核中
查看>>
IOS开发的开源库
查看>>
IOS开发的开源库
查看>>
Jenkins - sonarqube 代码审查
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成(一)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 单机部署(二)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
查看>>