兄弟連Go語言培訓分享閉包和錯誤處理

來源:互聯網
上載者:User

  “區塊鏈+時代無疑會是下一個風口,然而現在的區塊鏈行業專業型人才正在遭遇瓶頸”兄弟連教育區塊鏈學院院長尹成表示,“希望能通過兄弟連教育區塊鏈培訓學院為社會為企業培養並輸送更多優質的區塊鏈高精尖型技術人才。

Go語言中的閉包同樣也會引用到函數外的變數。閉包的實現確保只要閉包還被使用,那麼

被閉包引用的變數會一直存在,例如:package main

import "fmt"


func main(){

    var j int = 5

a := func()(func()) { //圓括弧中的func()表示傳回值是一個func()函數

        var i int = 10

return func() { //這裡返回一個匿名函數

            fmt.Printf("i, j: %v, %v\n", i, j)

        }

}() //花括弧後帶參數列表表示調用匿名函數,執行到這裡變數a就等於了一個函數了.


a() //調用函數a


j *= 2 //修改函數外部的變數j


a() //再次調用函數a

}


運行結果:

i, j: 10, 5

i, j: 10, 10


在上面的例子中,變數 a 指向的閉包函數引用了局部變數 i 和 j , i 的值被隔離,在閉包外不能被修改,改變 j 的值以後,再次調用 a ,發現結果是修改過的值。在變數 a 指向的閉包函數中,只有內部的匿名函數才能訪問變數 i ,而無法通過其他途徑訪問到,因此保證了 i 的安全性。


2.錯誤處理

2.1 error介面

Go語言引入了一個關於錯誤處理的標準模式,即 error 介面,該介面的定義如下:

type error interface {

    Error() string

}

建立error通常如下:

var e error = errors.New("...")//需要使用使用errors包


對於大多數函數,如果要返回錯誤,大致上都可以定義為如下模式,將 error 作為多種返回

值中的最後一個,但這並非是強制要求:

func Foo(param int)(res int,err error){

    //....

}


調用時的代碼建議按如下方式處理錯誤情況:

1

2

n, err := Foo(0)

if err != nil {

// 錯誤處理

} else {

// 使用傳回值n

}


2.2 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

}

我們看到上面有很多重複的代碼,Go的defer有效解決了這個問題。使用它後,不但代碼量減少了很多,而且程式變得更優雅。

func ReadWrite() bool {

    file.Open("file")

defer file.Close() //保證資源正常關閉

    if failureX {

        return false

    }

    if failureY {

        return false

    }

    return true

}


如果有很多調用defer,那麼defer是採用後進先出模式

1

2

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

defer fmt.Printf("%d ", i) //輸出結果:4 3 2 1 0

}


defer有點類似java中的try{}finall{}


2.3 panic和recover函數


Go語言有2個內建的函數panic()和recover(),用以報告和捕獲運行時發生的程式錯誤,與error不同,panic和recover一般用在函數內部。一定要注意不要濫用panic和recover,可能會導致效能問題,一般只在未知輸入和不可靠請求時使用。Go語言的錯誤處理流程:當一個函數在執行過程中出現了異常或遇到 panic(),正常語句就會立即終止,然後執行 defer 語句,再報告異常資訊,最後退出 goroutine。如果在defer中使用了recover()函數,則會捕獲錯誤資訊,使該錯誤資訊終止報告。如下樣本,例子來自網路

package main

import (

"log"  //log包

"strconv" //字元轉換包

)

//捕獲因未知輸入導致的程式異常

func catch(nums ...int) int {

    defer func() {

//recover()可以捕獲運行時發生的異常,避免異常時程式直接over,通常用在defer函數內

        if r := recover(); r != nil {

log.Println("[E]", r) //將捕獲的異常資訊通過log列印,而不會導致程式掛掉

        }

    }()

    return nums[1] * nums[2] * nums[3] //index out of range

}

//主動拋出 panic,不推薦使用,可能會導致效能問題

func toFloat64(num string) (float64, error) {

    defer func() {

        if r := recover(); r != nil {

            log.Println("[W]", r)

        }

    }()

    if num == "" {

panic("param is null") //主動拋出 panic

    }

    return strconv.ParseFloat(num, 10)

}


func main() {

    catch(2, 8)

    toFloat64("")

}


運行結果:

2016/03/26 20:16:03 [E] runtime error: index out of range

2016/03/26 20:16:03 [W] param is null

最後補充下nil的介紹:

golang的nil在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。

nil是預先說明的標識符,也即通常意義上的關鍵字。在golang中,nil只能賦值給指標、

channel、func、interface、map或slice類型的變數。如果未遵循這個規則,則會引發panic。

高能預警,兄弟連教育區塊鏈直播課程8月持續火爆來襲!

原價1188元的12節區塊鏈進階課程,現僅需1元!

還可免費領取《Go語言基礎實戰項目開發》與《Go語言進階實戰項目開發》教材兩本!!

限時限量!!先到先得!!

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


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.