Go函數(shù)類型的使用

he&遠(yuǎn)方 作品

人永遠(yuǎn)都無法知道自己該要什么,因?yàn)槿酥荒芑钜淮危炔荒苣盟笆老啾?,也不能在來生加以修正。沒有任何方法可以檢驗(yàn)?zāi)姆N抉擇是好的,因?yàn)椴淮嬖谌魏伪容^。一切都是馬上經(jīng)歷,僅此一次,不能準(zhǔn)備。from 《不能承受的生命之輕》

引用于:http://wufazhuce.com/one/1380

函數(shù)在Go語言中應(yīng)該是最頻繁使用的類型了,所以把Go語言定義為函數(shù)式編程語言,個(gè)人認(rèn)為也是一種正確的解釋。函數(shù)在Go中既有類似JS語言的用法,也有C、JAVA這種語言的身影。

和JS語言對(duì)比,函數(shù)有以下特性:

  • 普通函數(shù):作為一個(gè)普通方法使用。
  • 變長參數(shù):函數(shù)可以接收可變數(shù)目的參數(shù),這在JAVA里面也有類似用法。
  • 閉包函數(shù):JS中常用的一種模式,便于維護(hù)一些特殊作用域的變量等用法。
  • 對(duì)象中的方法:JS中類面向?qū)ο蟮囊环N寫法。

和C語言對(duì)比,函數(shù)有以下特性:

  • 多返回值:函數(shù)可以返回多個(gè)不同類型的結(jié)果。

Go自身定義的函數(shù)特性:

  • 巧用return:合理的利用return中斷程序邏輯,會(huì)使代碼顯得更簡潔易懂。
  • 作為參數(shù)傳遞:作為回調(diào)函數(shù)來說,更好的規(guī)范了回調(diào)函數(shù)引用的規(guī)范性。
  • 值傳遞:變量作為參數(shù)傳遞給函數(shù)時(shí),默認(rèn)是值傳遞,只是變量的一個(gè)拷貝,即副本。函數(shù)內(nèi)部只是對(duì)變量副本的操作,不會(huì)影響到實(shí)際變量本身。

普通函數(shù)、多返回值

// 普通函數(shù),不帶參數(shù)
func generalFun() {
    fmt.Println("普通函數(shù)")
}

// 普通函數(shù),帶參數(shù)
func generalFun1(i int, str string) {
    fmt.Printf("i=%d str=%s\n", i, str)
}

// 普通函數(shù),帶參數(shù)和返回一個(gè)結(jié)果
func generalFun2(i int, str string) string {
    tempStr := strconv.Itoa(i) + str
    return tempStr
}

// 普通函數(shù),帶參數(shù)和返回多個(gè)結(jié)果,需要用括號(hào)包含所有返回類型
func generalFun3(i int, str string) (int, string) {
    tempStr := strconv.Itoa(i) + str
    tempI := i + i
    return tempI, tempStr
}

上面示例中的普通函數(shù)用法,作為對(duì)象的方法也是同樣支持。

變長參數(shù)

格式:paramName ...type:可理解為函數(shù)可以接收type類型的可變參數(shù),參數(shù)名稱為paramName,在函數(shù)內(nèi)部可把paramName理解為類似slice類型的參數(shù)值??捎?code>for _, val := range paramName遍歷傳遞進(jìn)來的多個(gè)參數(shù)。

1、第一種用法:知道可變參數(shù)的類型時(shí):

func myfun(prefix string, who ...string) {
    //獲取可變參數(shù)的長度
    fmt.Println(len(who))
    for _, val := range who {
        fmt.Println(prefix, val)
    }
}


func Test_fun_Sample01(t *testing.T) {
    myfun("hello:", "Joe", "Anna", "Eileen")
}

Test_fun_Sample01 測試用例執(zhí)行結(jié)果:

hello: Joe
hello: Anna
hello: Eileen

2、第二種用法:不知道可變參數(shù)的類型時(shí):

如果一個(gè)變長參數(shù)的類型沒有被指定,則可以使用默認(rèn)的空接口 interface{},這樣就可以接受任何類型的參數(shù)。該方案不僅可以用于長度未知的參數(shù),還可以用于任何不確定類型的參數(shù)??墒褂?code>for-range循環(huán)以及switch結(jié)構(gòu)對(duì)每個(gè)參數(shù)的類型進(jìn)行判斷

type Person struct {
    name string
}

func test8(values ...interface{}) {
    for _, val := range values {
        switch v := val.(type) {
        case int:
            fmt.Println("val type is int ", v)
        case float64:
            fmt.Println("val type is float ", v)
        case string:
            fmt.Println("val type is string ", v)
        case bool:
            fmt.Println("val type is bool ", v)
        case Person:
            fmt.Println("val type is Person ", v.name)
        case *Person:
            fmt.Println("val type is *Person ", v.name)
        default:
            fmt.Println("val type is unknow ", v)
        }
    }
}

func Test_test8(t *testing.T) {
    temp_int := 1
    temp_float := 5.6
    temp_string := "hello"
    temp_bool := true
    temp_person1 := &Person{name: "jack"}
    temp_person2 := Person{name: "rose"}
    var temp_float32 float32 = 6.6

    test8(temp_int, temp_float, temp_string, temp_bool, temp_person1, temp_person2, temp_float32)
}

運(yùn)行結(jié)果:

val type is int 1
val type is float 5.6
val type is string hello
val type is bool true
val type is *Person jack
val type is Person rose
val type is unknow 6.6

示例中需要注意的兩個(gè)地方:

  1. float默認(rèn)定義的類型為float64。
  2. struct要區(qū)分傳遞的參數(shù)是 Person 類型的結(jié)構(gòu)體變量,還是 Person 類型的指針變量。

巧用return

1、第一種用法:無返回值函數(shù),在內(nèi)部任何程序執(zhí)行片段使用return ,直接會(huì)跳出該函數(shù),return下面的程序片段都不會(huì)再執(zhí)行。

func fun_return() {
    for i := 0; i < 10; i++ {
        fmt.Printf("%v ", i)
        if i == 3 {
            return
        }
    }
} //0 1 2 3

2、第二種用法:有返回值函數(shù),在內(nèi)部任何程序執(zhí)行片段使用return,它下面的程序片段都不會(huì)再執(zhí)行,但是程序結(jié)尾必須以return結(jié)束,否則程序報(bào)錯(cuò)。

func fun_return() int {
    for i := 0; i < 10; i++ {
        fmt.Printf("%v ", i)
        if i == 3 {
            return
        }
    }
    return i
} //0 1 2 3

上面兩個(gè)示例,執(zhí)行結(jié)果一樣,但是唯一不同的就是有返回值函數(shù)程序最后必須有return

值傳遞、引用傳遞

任何時(shí)候,如果要同步改變函數(shù)外聲明的變量的值時(shí),都要優(yōu)先考慮用指針傳遞,即占用內(nèi)存空間少,又執(zhí)行速度快。

基本類型的參數(shù)傳遞

func test3(str string) {
    str = "go"
    fmt.Printf("str=%s", str)
}

func test4(str *string) {
    *str = "go"
    fmt.Printf("str=%s", *str)
}

func Test_test3(t *testing.T) {
    temp := "hello"
    test3(temp)
    fmt.Println(" temp=", temp) //str=go temp= hello

    test4(&temp)
    fmt.Println(" temp=", temp) //str=go temp= go
}

struct類型的參數(shù)傳遞,及對(duì)象傳遞

type Person struct {
    name string
}

// 傳遞Person struct類型的變量
func test5(p Person) {
    p.name = "go" // 此時(shí)的p為參數(shù)副本
    fmt.Printf("Person.name = %s", p.name)
}

// 傳遞指向Person struct類型的的變量地址
func test6(p *Person) {
    p.name = "go"
    fmt.Printf("Person.name = %s", p.name)
}

func Test_test5(t *testing.T) {
    p := Person{"hello"}
    test5(p)
    fmt.Println(" p.name=", p.name) //Person.name = go p.name= hello

    test6(&p)
    fmt.Println(" p.name=", p.name) //Person.name = go p.name= go

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

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,537評(píng)論 19 139
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,674評(píng)論 0 4
  • 1、c語言的函數(shù)有以下特點(diǎn): (1)才源程序由函數(shù)組成,一個(gè)主函數(shù)main()+若干其他函數(shù) C程序中的函數(shù)類似文...
    滕王閣序閱讀 1,521評(píng)論 0 6
  • 坐了幾個(gè)小時(shí)的火車,終于來到了這里。 邊走邊看,這里的景,這里的人,這里的安靜與熱鬧。 興奮的嘴角一直上揚(yáng)。 這里...
    來搞事情啦閱讀 358評(píng)論 0 5
  • 1999年12月20日,被葡萄牙占領(lǐng)4個(gè)世紀(jì)的澳門終于回到祖國母親的懷抱。 祖國母親,的固定搭配出現(xiàn)在20世紀(jì)初,...
    松球42閱讀 309評(píng)論 0 1

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