Go入門系列(四)函數(shù)

目錄:
一、基礎(chǔ)
二、匿名
三、接口
四、錯誤處理

一、基本函數(shù)

Go語言的函數(shù)聲明格式為:

func function_name( [parameter list] ) [return_types] {
   函數(shù)體
}
func:函數(shù)由 func 開始聲明
function_name:函數(shù)名稱,函數(shù)名和參數(shù)列表一起構(gòu)成了函數(shù)簽名。
parameter list:參數(shù)列表,參數(shù)就像一個占位符,當函數(shù)被調(diào)用時,你可以將值傳遞給參數(shù),這個值被稱為實際參數(shù)。參數(shù)列表指定的是參數(shù)類型、順序、及參數(shù)個數(shù)。參數(shù)是可選的,也就是說函數(shù)也可以不包含參數(shù)。
return_types:返回類型,函數(shù)返回一列值。return_types 是該列值的數(shù)據(jù)類型。有些功能不需要返回值,這種情況下 return_types 不是必須的。
函數(shù)體:函數(shù)定義的代碼集合。

基本的聲明、調(diào)用、傳參方式如下:

func main() {
    a,b:=who("rabbit",18)
    fmt.Println(a,b)
}

func who(name string, age int) (string, int) {
    return name, age
}
#輸出
rabbit 18

二、匿名函數(shù)

匿名函數(shù)是指不需要定義函數(shù)名的一種函數(shù)實現(xiàn)方式,由一個不帶函數(shù)名的函數(shù)聲明和函數(shù)體組成,上一章我們提到過,函數(shù)類型是變量的一種,所以匿名函數(shù)往往以變量方式傳遞。
可以使用變量傳遞然后賦值:

func main() {
    who:=func (name string, age int) (string, int) {
        return name, age
    }
    a,b:=who("rabbit",18)
    fmt.Println(a,b)
}
#輸出
rabbit 18

也可以直接賦值:

func main() {
    a,b:=func (name string, age int) (string, int) {
        return name, age
    }("rabbit",18)
    fmt.Println(a,b)
}
#輸出
rabbit 18

其使用方式類似C語言中的回調(diào)函數(shù)。
另外在此我們再回顧一個概念:閉包函數(shù),聲明在一個函數(shù)中的函數(shù),叫做閉包函數(shù),而Go語言中的匿名函數(shù)機制,完美符合閉包函數(shù)的設(shè)定。
其實閉包函數(shù)和匿名函數(shù)的概念在很多語言中很難區(qū)分,至于我的理解,其實他倆并沒有直接關(guān)系,至少匿名函數(shù)的使用這個行為構(gòu)成了閉包。
多說一句很多其他語言的老玩家都深有感觸,過度使用閉包容易造成內(nèi)存的浪費,但這一點再Go語言中把控的比較嚴格,筆者作為入門新人不做太多評論,日后再來反饋。

三、接口

接口,在軟件開發(fā)流程中對團隊契合度來講是個極其重要的地方,簡單說調(diào)用方和實現(xiàn)方均需要遵守的一種協(xié)議,大家按照統(tǒng)一的方法命名參數(shù)類型和數(shù)量來協(xié)調(diào)邏輯處理的過程。
然后對于我們個人開發(fā)來講,也會方便自己對項目代碼進行合理的維護和功能拓展。
接口格式規(guī)則為:

type 接口類型名 interface{
    方法名1( 參數(shù)列表1 ) 返回值列表1
    方法名2( 參數(shù)列表2 ) 返回值列表2
    …
}

我們通過樣例來實現(xiàn)一個反饋用戶信息的功能:

package main
import (
    "fmt"
    "time"
)

type UserInfo interface {
    login(name string)
    info(name string,age int,city string)
}


type People struct {
    name    string
    age int
    city    string
}


func (people People) login(name string) {
    fmt.Printf("%s您好,歡迎登陸\n登錄時間為:%s\n",name,time.Now())
}

func (people People) info(name string,age int,city string) {
    fmt.Printf("您的個人資料為:姓名:%s 年齡:%d 城市:%s\n",name,age,city)
}


func main() {
    var userinfo UserInfo
    userinfo = new(People)
    userinfo.login("rabbit")
    userinfo.info("rabbit",18,"Shandong")
}
#輸出
rabbit您好,歡迎登陸
登錄時間為:2020-03-14 16:26:35.2352272 +0800 CST m=+0.003989101
您的個人資料為:姓名:rabbit 年齡:18 城市:Shandong

此外接口還允許嵌套使用,將多個接口進行組合,作為入門系列我們簡單提及暫不做代碼展開。

四、錯誤處理

錯誤處理,區(qū)別與其他語言中的異常處理。其他語言的老玩家不得不承認一個事實,所謂的異常捕捉機制,倒不如說異常屏蔽機制,異常依然發(fā)生了,只不過通過該機制進行了屏蔽不影響程序運行。
Go語言的設(shè)計者認為其他語言的異常機制已被過度使用,上層邏輯需要為函數(shù)發(fā)生的異常付出太多的資源,同時,如果函數(shù)使用者覺得錯誤處理很麻煩而忽略錯誤,那么程序?qū)⒃诓豢深A(yù)知的時刻崩潰。
Go語言希望開發(fā)者將錯誤處理視為正常開發(fā)必須實現(xiàn)的環(huán)節(jié),正確地處理每一個可能發(fā)生錯誤的函數(shù),同時,Go語言使用返回值返回錯誤的機制,也能大幅降低編譯器、運行時處理錯誤的復雜度,讓開發(fā)者真正地掌握錯誤的處理。
綜上所述,Go語言不會為你屏蔽異常,它需要你正視可能出現(xiàn)的問題并手動去給出異常提示。
其二,為什么錯誤處理放到了這一章節(jié),因為Go語言錯誤處理的機制其本質(zhì)正是接口。
error類型是一個接口類型,這是它的定義:

type error interface {
    Error() string
}

后邊我們在使用官方包的時候會接觸很多已經(jīng)定義好的錯誤提示,在這里我們先嘗試自定義錯誤,我們可以在編碼中通過實現(xiàn) error 接口類型來生成錯誤信息,函數(shù)通常在最后的返回值中返回錯誤信息。使用errors.New 可返回一個錯誤信息。
這么說可能有點抽象,我們嘗試繼續(xù)升級我們上面的例子,比如加入年齡錯誤檢測。

package main
import (
    "errors"
    "fmt"
    "time"
)

type UserInfo interface {
    login(name string)
    info(name string,age int,city string)
}

func AgeTure(age int) (int, error) {
    if age < 0 || age > 200 {
        return 0, errors.New("請正確輸入您的年齡!")
    }else {
        return 1, nil
    }
}

type People struct {
    name    string
    age int
    city    string
}


func (people People) login(name string) {
    fmt.Printf("%s您好,歡迎登陸\n登錄時間為:%s\n",name,time.Now())
}

func (people People) info(name string,age int,city string) {
    result, err:= AgeTure(age)

    if err != nil {
        fmt.Println(result,err)
    }else {
        fmt.Printf("您的個人資料為:姓名:%s 年齡:%d 城市:%s\n",name,age,city)
    }
}


func main() {
    var userinfo UserInfo
    userinfo = new(People)
    userinfo.login("rabbit")
    userinfo.info("rabbit",1988,"Shandong")
}
#輸出
rabbit您好,歡迎登陸
登錄時間為:2020-03-15 12:40:52.8176698 +0800 CST m=+0.003991401
0 請正確輸入您的年齡!

我們鍵入了錯誤的年齡,觸發(fā)了自定義錯誤提示,其中nil是go語言中預(yù)先定義的標識符,可看作是其他語言中的null(NULL),我們可以直接使用nil,而不用聲明它。
另外多說一句,go其實確實保留了類似其他語言的異常處理機制,但有區(qū)別,但是官方的目的是為了調(diào)試,而非讓你掩蓋異常,所以我們選擇適應(yīng)這個語言,僅在此簡單提及:panic 與 recover 是 Go 的兩個內(nèi)置函數(shù),這兩個內(nèi)置函數(shù)用于處理 Go 運行時的錯誤,panic 用于主動拋出錯誤,recover 用來捕獲 panic 拋出的錯誤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容