Go語(yǔ)言學(xué)習(xí)筆記 - 函數(shù)

函數(shù)

不支持 嵌套 (nested)于游、重載 (overload) 和 默認(rèn)參數(shù) (default parameter)毁葱。
? 無(wú)需聲明原型。
? 支持不定長(zhǎng)變參贰剥。
? 支持多返回值倾剿。
? 支持命名返回參數(shù)。
? 支持匿名函數(shù)和閉包蚌成。
使用關(guān)鍵字 func 定義函數(shù),左大括號(hào)依舊不能另起一行前痘。

func test(x,y int,s string) (int string) { //類(lèi)型相同的相鄰參數(shù)可合并。
    n := x + y //多值返回必須用括號(hào)
    return n, fmt.Sprintf(s,n)
}

函數(shù)是第一類(lèi)對(duì)象,可作為參數(shù)傳遞担忧。建議將復(fù)雜簽名定義為函數(shù)類(lèi)型,以便于閱讀清笨。

func test(fn func() int) int {
    return fn()
}

type FormatFunc func(s string, x,y int) string //定義函數(shù)類(lèi)型

func format(fn FormatFunc, s string, x,y int) string {
    return fn(s,x,y)
}

func main() {
    s1 := test(func() int { return 100}) //直接將匿名函數(shù)當(dāng)參數(shù)

    s2 := format(func(s string, x, y int) string {
        return fmt.Sprintf(s, x, y)
    }, "%d, %d", 10, 20)
    println(s1, s2)

變參

變參本質(zhì)上就是slice过蹂。只能有一個(gè),且必須是最后一個(gè)參數(shù)位。

func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }
    return fmt.Sprintf(s, x)
}

func main() {
    println(test("sum: %d", 1, 2, 3))
}

使用slice對(duì)象做變參時(shí)翘盖,必須展開(kāi)督赤。

func main() {
    s := []int{1, 2, 3}
    println(test("sum: %d",s...))
}

返回值

不能用容器對(duì)象接收多返回值霉颠。只能用多個(gè)變量猬仁,或“_”忽略。多個(gè)返回值可直接作為其他函數(shù)調(diào)用實(shí)參轧房。

func test() (int, int) {
    return 1, 2
}

func add(x, y int) int {
    return x + y
}

func sum(n ...int) int {
    var x int
    for _, i := range n {
        x += i
    }
    return x
}

func main() {
    println(add(test()))
    println(sun(test()))
}

命名返回參數(shù)可看做與形參類(lèi)似的局部變量,最后由 return 隱式返回拌阴。

func add(x, y int) (z int) {
    z = x + y
    return
}
func main() {
    println(add(1, 2))
}

命名返回參數(shù)可被同名局部變量遮蔽,此時(shí)需要顯式返回。

func add(x, y int) (z int) {
  {// 不能在一個(gè)級(jí)別,引發(fā) "z redeclared in this block" 錯(cuò)誤奶镶。
      var z = x + y
      // return // Error: z is shadowed during return
      return z // 必須顯式返回迟赃。
  }
}

命名返回參數(shù)允許 defer 延遲調(diào)用通過(guò)閉包讀取和修改陪拘。

func add(x, y int) (z int) {
    defer func() {
        z += 100
    }()
    z = x + y
    return
}

func main() {
    println(add(1, 2)) //輸出:103
}

顯式 return 返回前,會(huì)先修改命名返回參數(shù)。

func add(x, y int) (z int) {
    defer func() {
        println(z)  //輸出:203
    }()

    z = x + y
    return z + 200
}

func main() {
    println(add(1, 2))  //輸出:203
}

匿名函數(shù)可賦值給變量,做為結(jié)構(gòu)字段,或者在 channel 里里傳送纤壁。閉包復(fù)制的是原對(duì)象指針,這就很容易解釋延遲引用現(xiàn)象藻丢。

延遲調(diào)用

關(guān)鍵字 defer 用于注冊(cè)延遲調(diào)用。這些調(diào)用直到 ret 前才被執(zhí)行摄乒,通常用于釋放資源或錯(cuò)誤處理。多個(gè) defer 注冊(cè)残黑,按 FILO 次序執(zhí)行馍佑。哪怕函數(shù)或某個(gè)延遲調(diào)用發(fā)生錯(cuò)誤,這些調(diào)用依舊會(huì)被執(zhí)行梨水。

濫用 defer 可能會(huì)導(dǎo)致性能問(wèn)題,尤其是在一個(gè) "大循環(huán)" 里拭荤。

var log sync.Mutex
func test() {
    lock.Lock()
    lock.Unlock()
}
func testdefer() {
    lock.Lock()
    defer lock.Unlock()
}
func BenchmarkTest(b *testging.B) {
    for i := 0; i < b.N; i++ {
        test()
  }
}
func BenchmarkTestDefer(b *testging.B) {
    for i := 0; i < b.N; i++ {
        testdefer()
  }
}
//輸出:
BenchmarkTest    50000000  43 ns/op
BenchmarkTestDefer 20000000  128 ns/op

錯(cuò)誤處理

沒(méi)有結(jié)構(gòu)化異常,使用panic拋出錯(cuò)誤疫诽,recover捕獲錯(cuò)誤舅世。由于 panic、recover 參數(shù)類(lèi)型為 interface{},因此可拋出任何類(lèi)型對(duì)象奇徒。捕獲函數(shù) recover 只有在延遲調(diào)用內(nèi)直接調(diào)用才會(huì)終止錯(cuò)誤,否則總是返回 nil雏亚。任何未
捕獲的錯(cuò)誤都會(huì)沿調(diào)用堆棧向外傳遞。

func test() {
  defer func() {
        if err := recover(); err != nil {
            println(err.(string)) // 將interface{}轉(zhuǎn)型為string類(lèi)型
    }()
    panic("panic erro!")
}

除用 panic 引發(fā)中斷性錯(cuò)誤外,還可返回 error 類(lèi)型錯(cuò)誤對(duì)象來(lái)表示函數(shù)調(diào)用狀態(tài)摩钙。標(biāo)準(zhǔn)庫(kù) errors.New 和 fmt.Errorf 函數(shù)用于創(chuàng)建實(shí)現(xiàn) error 接口的錯(cuò)誤對(duì)象罢低。通過(guò)判斷錯(cuò)誤對(duì)象實(shí)例來(lái)確定具體錯(cuò)誤類(lèi)型。如何區(qū)別使用 panic 和 error 兩種方式?

慣例是:導(dǎo)致關(guān)鍵流程出現(xiàn)不可修復(fù)性錯(cuò)誤的使用 panic,其他使用 error胖笛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末网持,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子长踊,更是在濱河造成了極大的恐慌功舀,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件身弊,死亡現(xiàn)場(chǎng)離奇詭異辟汰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)阱佛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)莉擒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瘫絮,你說(shuō)我怎么就攤上這事涨冀。” “怎么了麦萤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵鹿鳖,是天一觀的道長(zhǎng)扁眯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)翅帜,這世上最難降的妖魔是什么姻檀? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮涝滴,結(jié)果婚禮上绣版,老公的妹妹穿的比我還像新娘。我一直安慰自己歼疮,他們只是感情好杂抽,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著韩脏,像睡著了一般缩麸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赡矢,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天杭朱,我揣著相機(jī)與錄音,去河邊找鬼吹散。 笑死弧械,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的空民。 我是一名探鬼主播梦谜,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼袭景!你這毒婦竟也來(lái)了唁桩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤耸棒,失蹤者是張志新(化名)和其女友劉穎荒澡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體与殃,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡单山,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幅疼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片米奸。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖爽篷,靈堂內(nèi)的尸體忽然破棺而出悴晰,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布铡溪,位于F島的核電站漂辐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏棕硫。R本人自食惡果不足惜髓涯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哈扮。 院中可真熱鬧纬纪,春花似錦、人聲如沸滑肉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赦邻。三九已至,卻和暖如春实檀,著一層夾襖步出監(jiān)牢的瞬間惶洲,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工膳犹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恬吕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓须床,卻偏偏與公主長(zhǎng)得像铐料,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子豺旬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 原文地址:C語(yǔ)言函數(shù)調(diào)用棧(一)C語(yǔ)言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過(guò)程可看作連續(xù)的函數(shù)調(diào)用钠惩。當(dāng)一個(gè)函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,629評(píng)論 1 19
  • 能力模型 選擇題 [primary] 下面屬于關(guān)鍵字的是()A. funcB. defC. structD. cl...
    _張曉龍_閱讀 24,845評(píng)論 14 224
  • 1、范型范型所解決的問(wèn)題 函數(shù)族阅、方法篓跛、類(lèi)型:類(lèi),結(jié)構(gòu)體坦刀,枚舉愧沟,元組類(lèi)型,協(xié)議參數(shù)鲤遥,返回值沐寺,成員函數(shù)參數(shù),成員屬性類(lèi)...
    我是小胡胡123閱讀 836評(píng)論 0 1
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,523評(píng)論 1 51
  • 接著上上節(jié) thread 盖奈,本節(jié)主要介紹mutex的內(nèi)容混坞,練習(xí)代碼地址。<mutex>:該頭文件主要聲明了與互斥量...
    jorion閱讀 12,509評(píng)論 2 4