培训首页  >  web前端新闻  >  兄弟连Go语言中的defer使用

兄弟连Go语言中的defer使用

[2018-08-24 13:53:16] 浏览量:74 来源:

北京兄弟连IT

  所有的新技术都经历了一些成长的痛苦,区块链技术也一样。但是,尽管它还处于发展的早期阶段,但它具有改进许多行业、许多应用和系统的巨大潜力。

 

  Go语言具有其关键特性。Go语言之所以如此强大,是因为它在服务端的开发中总能抓住程序员的痛痒需求,用直接、简单、、稳定的方式来解决并实现问题。

 

defer

Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:

 

func ReadWrite() bool {

    file.Open("file")

// 做一些工作

    if failureX {

        file.Close()

        return false

    }

 

    if failureY {

        file.Close()

        return false

    }

 

    file.Close()

    return true

}

我们看到上面有很多重复的代码,Godefer有效解决了这个问题。使用它后,不但代码量减少了很多,而且程序变得更优雅。在defer后的函数会在函数退出前调用。

 

func ReadWrite() bool {

    file.Open("file")

    defer file.Close()

    if failureX {

        return false

    }

    if failureY {

        return false

    }

    return true

}

如果有很多调用defer,那么defer是采用后进先出模式,所以如下代码会输出4 3 2 1 0

 

for i := 0; i < 5; i++ {

    defer fmt.Printf("%d ", i)

}

 

defer 给我的印象就是,类似java中的

 

try {

 

}finally {

 

}

 

我目前的理解就是,在函数块中使用defer,就是函数对应的有一个栈空间,先进后出。需要函数结束后调用栈,来出发defer操作。

 

如果,一个对象的创建,很消耗内存,需要及时关闭,defer无法像try finnaly哪样准确。

 

package main

 

import "fmt"

import "time"

 

type User struct {

        username string

}

 

func (this *User) Close() {

        fmt.Println(this.username, "Closed !!!")

}

 

func main() {

        u1 := &User{"jack"}

        defer u1.Close()

        u2 := &User{"lily"}

        defer u2.Close()

 

        time.Sleep(10 * time.Second)

 

        fmt.Println("Done !")

 

}

[vicky@localhost goroutine]$

 

[vicky@localhost goroutine]$ go run deferTest1.go

Done !

lily Closed !!!

jack Closed !!!

[vicky@localhost goroutine]$

 

实际上,线程Sleep10秒,u1,和u2早就可以Close()了,但却需要依赖main()函数的结束,才能defer执行。

 

那么尝试给defer添加内部代码区:

 

package main

 

import "fmt"

import "time"

 

type User struct {

        username string

}

 

func (this *User) Close() {

        fmt.Println(this.username, "Closed !!!")

}

 

func main() {

        {

                // 即便加了代码快范围,依旧也要主函数体结束才执行defer

                u1 := &User{"jack"}

                defer u1.Close()

        }

        u2 := &User{"lily"}

        defer u2.Close()

 

        time.Sleep(10 * time.Second)

 

        fmt.Println("Done !")

 

}

 

Done !

lily Closed !!!

jack Closed !!!

[vicky@localhost goroutine]$

 

依旧defer的执行在Done!后。那么如何才能达到try finally 哪样准确的Close呢?

 

package main

 

import "fmt"

import "time"

 

type User struct {

        username string

}

 

func (this *User) Close() {

        fmt.Println(this.username, "Closed !!!")

}

 

func main() {

        u1 := &User{"jack"}

        f(u1) // 这样的方式,u1才会不依赖main函数的执行

 

        // 这样的方式,u2也不会依赖main函数的执行

        u2 := &User{"lily"}

        // m := func() {

        //         defer u2.Close()

        //         // u2 do somthing

        // }

        // m()

        func() {

                 defer u2.Close()

                 // u2 do somthing

        }()

        time.Sleep(10 * time.Second)        fmt.Println("Done !")}func f(u *User) {        defer u.Close()        // u1 do gomething}

 

这样的使用方式,视乎不太合理,但却有存在的必要性。大多数情况下,可以用于 u1,u2  之类非常消耗内存,或者cpu,其后执行时间过程且没有太多关联的情况。既保留了defer的功能特性,也满足范围控制的条件!

高能预警,兄弟连教育区块链直播课程8月持续火爆来袭!

原价1188元的12节区块链进阶课程,现仅需1元!

还可取《Go语言基础实战项目开发》与《Go语言实战项目开发》教材两本!!

限量!!先到先得!!

http://www.ydma.cn/open/course/24


关注兄弟连区块链技术公众号领取更多技术干货哦!!!



文中图片素材来源网络,如有侵权请联系删除
  • 软件开发
  • 软件测试
  • 数据库
  • Web前端
  • 大数据
  • 人工智能
  • 零基础
  • 有HTML基础
  • 有PHP基础
  • 有C语言基础
  • 有JAVA基础
  • 其他计算机语言基础
  • 周末班
  • 全日制白班
  • 随到随学

网上报名

热门信息