­

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

  • 2019 年 10 月 25 日
  • 筆記

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

好了,話不多說,我們開始今天的分享,今天分享的主題是關於go語言系列中的延遲調用和作用域相關的知識。

延遲調用defer

在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 會有怎樣的效果呢?

            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 = %dn", a, b)                    /*                          運行結果:                          a = 20, b = 120                          defer: 10 120                  */          }

所以在運行結果上看,使用了defer會先進行傳值,然後是最後才會計算出來

獲取命令行參數

    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 = %dn", a, b, c)  }    func main() {          //a, b, c = 1, 2, 3 //err, a, b, c不屬於此作用域          {                  var i int                  i = 10                  fmt.Printf("i = %dn", 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 = %dn", a)  }    func main() {          a = 10          fmt.Printf("main a = %dn", a) //main a = 10            test() //test a = 10  }

不同作用域同名變數

在不同作用域可以聲明同名的變數,其訪問原則為:在同一個作用域內,就近原則訪問最近的變數,如果此作用域沒有此變數聲明,則訪問全局變數,如果全局變數也沒有,則報錯。
var a int //全局變數的聲明

func test01(a float32) {          fmt.Printf("a type = %Tn", a) //a type = float32  }    func main() {          fmt.Printf("a type = %Tn", a) //a type = int, 說明使用全局變數的a            var a uint8 //局部變數聲明            {      var a float64                  //局部變數聲明      fmt.Printf("a type = %Tn", a) //a type = float64          }            fmt.Printf("a type = %Tn", a) //a type = uint8            test01(3.14)          test02()  }        func test02() {      fmt.Printf("a type = %Tn", a) //a type = int  }

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

file

本文由部落格一文多發平台 OpenWrite 發布!