Go語言入門——函數

寫了快一個月的Go,已經沒有什麼陌生感了。bash

一行代碼寫完,不會在行尾本能的敲上「;」,直接Enter鍵換行;架構

定義變量把變量名放在前面,類型放在後面;框架

使用struct去定義本身想要的數據模型就比如定義一個Java中的model同樣……函數

這些不用能夠通過大腦加工思考,就想本身還在寫Java同樣。微服務

還記得當時在看《Go實戰》的時候看到變量類型後置的聲明方式,我還在極力吐槽這種不人性的語法,若是我已經站在了真香的隊伍裏,和其餘的真香同窗別無二致。工具

感慨,人的適應能力真的強👍ui

做爲一個Java重度愛好者,其實在每次寫Go的時候都會不由自主的把二者進行對比,在寫文章的時候也會常常提到。固然了,今天主要說的仍是Go的函數。spa

一、Go語言中的函數長啥樣

func f(a int, b int) (ret int, err error) {
    fmt.Println("This is function")
    return
}
複製代碼

沒錯,這大概就是一個典型的Go風格的函數,那麼它有哪些特點code

  • 入參
  • 返回值

二、入參

參數合併聲明

入參的變量也是變量後置的,這裏a變量和b變量是相同類型的,因此也能夠寫成cdn

a, b int
複製代碼

對於不一樣類型的參數須要分開定義。

不定參數

除此之外,入參還支持不定參數

好比能夠這樣定義

func f(args ...int) {
    for _, arg := range args {
        fmt.Println(arg)
    }
}
複製代碼

針對不定參數的函數,咱們能夠這樣調用

f(1)

f(1, 2)

f(1, 2, 3)

避免了咱們在函數裏定義一長串變量的狀況。

上面的不定參數是int類型的,那麼是否支持多種類型混用的不定參數呢?

是能夠的,使用...interface{}這種形式

func f(args ...interface{}) {
    for _, arg := range args {
        switch arg.(type) {
            case int:
            	fmt.Println("It is int type")
            case string:
            	fmt.Println("It is string type")
            case int64:
            	fmt.Println("It is int64 type")
        }
    }
}
複製代碼

注意,這裏的i.(T)形式不是強制轉換或者隱式類型轉換,這是類型斷言,表示斷定類型的。

Go裏面是沒有隱式類型轉換的,不只沒有,並且強制類型轉換也很嚴格。

三、返回值

返回參數

不一樣於Java,Go函數是能夠支持多返回值的,好比這裏返回了ret和err兩個參數。

返回值的定義方式也很靈活,能夠寫成

func f(a int, b int) (int, error) {
    fmt.Println("This is function")
    return
}
複製代碼

若是返回只有一個參數能夠寫成

func f(a int, b int) (ret int) {
    fmt.Println("This is function")
    return
}
複製代碼

或者

func f(a int, b int) int {
    fmt.Println("This is function")
    return
}
複製代碼

「_」的用法

在前面的文章,咱們也順帶提過,對於函數返回的值,有些咱們不關心或者不須要的話,咱們不能抹掉他的位置,可是可使用"_"來表示這個參數的存在,只是不用而已,好比這樣調用上面的函數是不行的

ret := f(1, 2)	// 缺乏err返回值
複製代碼

可是這樣是OK的

ret, _ := f(1, 2)	
複製代碼

或者這樣

_, err := f(1, 2)	
複製代碼

error

error接口是Go標準庫爲了錯誤處理提供的接口。

通常在業務代碼中,咱們會調用某個方法後,斷定方法對應的值是否爲nil斷定方法是否被正常執行

if err != nil {
    // 沒有正常執行
} else {
    // 正常執行
}
複製代碼

panic和recover和defer

說到error,正好說說panic()和recover()兩個函數

當咱們遇到一些err的時候,咱們可能就會直接拋出panic,這裏的panic能夠近似理解爲Java裏面的Exception,即拋出異常。

if err != nil {
    panic(err)
}
複製代碼

一旦拋出panic,則程序將會終止,除非遇到一種狀況,即有recover的存在。

說到recover則不得不提defer

defer是Go裏面的新特性,有點類型Java裏面的finally,承擔回收資源或者解鎖這類的收尾工做,可是比finally要靈活,Go函數的defer能夠放在函數的任意位置,無論函數是否正常執行,在跳出函數前都會執行defer定義的函數。

接着說recover,若是在函數拋出panic,只要在最後遇到recover也是能夠恢復正常的,形式以下

defer func() {
    if ret := recover(); ret != nil {
        fmt.Println("Catch Runtime Error:)
    }
}
複製代碼

四、其餘

說說func

每一個函數都以func開始,來代表本身是一個函數。

那麼學過Java的確定會問,沒有像public、private這樣的訪問修飾符嗎?

沒有,可是Go經過另一種規則實現了訪問範圍便可見性。對於函數名使用大寫字母開頭,則表示能夠被其餘包使用,若是使用小寫字母開頭,則只能本包內使用。

固然,這個規則,也適用於變量的聲明。

匿名函數

和Java等其餘語言同樣,Go函數也有匿名函數。

func (a, b int, s string) int {
    ...
}
複製代碼

能夠經過直接在後面賦值的方式直接執行

func (a, b int, s string) int {
    ...
}(1, 2, "test")
複製代碼

這裏主要從Go語言的函數構成包括關鍵字func,入參和返回值介紹Go函數的一些特性。固然了,Go函數還有不少靈活性就再也不一一闡述了,有待你我在業務項目中慢慢實踐體會了。

五、技術沙龍

今天去參加了一個技術沙龍,主題是數據存儲與微服務架構實踐方面的。

這是本身第一次除了參加公司組織的各類會議之外,本身主動報名的線下技術沙龍。

會上聽到了阿里、百度的大佬分享關於過去的技術沉澱和對將來技術方向的展望,總體仍是蠻有收穫的。

拓寬了本身的知識面,也加深了對一些框架或者工具的理解,好比ServiceMesh。以前對於ServiceMesh的理解僅限於閱讀各類文章,本身的理解也比較有限,此次經過阿里大佬的解釋,更加清晰的瞭解了ServiceMesh以及它的優點。

最後曬一下在回答問題環節,主辦方送的馬克杯,好評

我的公衆號:JackieZheng 我會將我最新的文章推送給您,並和您一塊兒分享我平常閱讀過的優質文章

相關文章
相關標籤/搜索