Go語言系列開發之延遲調用和做用域

Hello,各位小夥伴你們好,我是小棧君,最近一段時間咱們將繼續分享關於go語言基礎系列,固然後期小棧君已經在籌劃關於java、Python,數據分析、人工智能和大數據等相關係列文章。但願能和你們一塊兒學習進步,相互提升。java

好了,話很少說,咱們開始今天的分享,今天分享的主題是關於go語言系列中的延遲調用和做用域相關的知識。閉包

延遲調用deferide

在go語言中關鍵字 defer ⽤於延遲一個函數或者方法(或者當前所建立的匿名函數)的執行。注意,defer語句只能出如今函數或方法的內部。因此咱們經常使用做關閉流處理或則須要進行延期處理的操做。函數

func main() {
        defer fmt.Println("小棧君在測試defer") //main結束前調用
        fmt.Println("this is a test")

        /*
                運行結果:
                this is a test
                小棧君在測試defer
        */
}

defer語句常常被用於處理成對的操做,如打開、關閉、鏈接、斷開鏈接、加鎖、釋放鎖。經過defer機制,不論函數邏輯多複雜,都能保證在任何執行路徑下,資源被釋放。釋放資源的defer應該直接跟在請求資源的語句後。學習

多個defer執行順序測試

若是一個函數中有多個defer語句,它們會以LIFO(後進先出)的順序執行。哪怕函數或某個延遲調用發生錯誤,這些調用依舊會被執⾏。大數據

func test(x int) {
fmt.Println(10 / x)//x爲0時,產生異常
}

func main() {
        defer fmt.Println("111")
        defer fmt.Println("222")

        defer test(0)

        defer fmt.Println("333")
        /*
        運行結果:
        333
        222
        111
        panic: runtime error: integer divide by zero
        */
}

defer和匿名函數結合使用
小棧君這邊直接爲你們舉例說明在匿名函數中使用defer 會有怎樣的效果呢?ui

func main() {
                a, b := 10, 20
                defer func(x int) { // a以值傳遞方式傳給x
                        fmt.Println("defer:", x, b) // b 閉包引用
                }(a)

                a += 10
                b += 100

                fmt.Printf("a = %d, b = %d\n", a, b)

                /*
                        運行結果:
                        a = 20, b = 120
                        defer: 10 120
                */
        }

因此在運行結果上看,使用了defer會先進行傳值,而後是最後纔會計算出來this

獲取命令行參數人工智能

package main
            import (
            "fmt"
            "os"
            )
                func main() {
                // IT小棧君
                agers := os.Args
                // 若是用戶輸入不正確或個數不對 則提醒
                if agers != nil && len(agers) < 2 {
                fmt.Println("小棧君提醒你,您輸入的位數不正確~")
                return
                }
                fmt.Println("小棧君告訴你實際傳參==》", agers)
                }

運行結果以下:

file

做用域
做用域爲已聲明標識符所表示的常量、類型、變量、函數或包在源代碼中的做用範圍。就比如是你在行車過程當中所可以行使的範圍同樣。

局部變量

在函數體內聲明的變量、參數和返回值變量就是局部變量,它們的做用域只在函數體內:

func test(a, b int) {
        var c int
        a, b, c = 1, 2, 3
        fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}

func main() {
        //a, b, c = 1, 2, 3 //err, a, b, c不屬於此做用域
        {
                var i int
                i = 10
                fmt.Printf("i = %d\n", i)
        }

        //i = 20 //err, i不屬於此做用域

        if a := 3; a == 3 {
                fmt.Println("a = ", a)
        }
        //a = 4 //err,a只能if內部使用
}

全局變量

在函數體外聲明的變量稱之爲全局變量,全局變量能夠在整個包甚至外部包(被導出後)使用。
var a int //全局變量的聲明

func test() {
        fmt.Printf("test a = %d\n", a)
}

func main() {
        a = 10
        fmt.Printf("main a = %d\n", a) //main a = 10

        test() //test a = 10
}

不一樣做用域同名變量

在不一樣做用域能夠聲明同名的變量,其訪問原則爲:在同一個做用域內,就近原則訪問最近的變量,若是此做用域沒有此變量聲明,則訪問全局變量,若是全局變量也沒有,則報錯。
var a int //全局變量的聲明

func test01(a float32) {
        fmt.Printf("a type = %T\n", a) //a type = float32
}

func main() {
        fmt.Printf("a type = %T\n", a) //a type = int, 說明使用全局變量的a

        var a uint8 //局部變量聲明

        {
    var a float64                  //局部變量聲明
    fmt.Printf("a type = %T\n", a) //a type = float64
        }

        fmt.Printf("a type = %T\n", a) //a type = uint8

        test01(3.14)
        test02()
}

    func test02() {
    fmt.Printf("a type = %T\n", a) //a type = int
}

今天的分享就到這裏就結束啦,若是你喜歡個人分享,麻煩你點擊再看,分享或留言,我是小棧君,咱們下期見,拜了個拜~

file

本文由博客一文多發平臺 OpenWrite 發佈!

相關文章
相關標籤/搜索