go閉包

匿名函數(shù)同樣被稱之為閉包(函數(shù)式語(yǔ)言的術(shù)語(yǔ)):它們被允許調(diào)用定義在其它環(huán)境下的變量荚藻。閉包可使得某個(gè)函數(shù)捕捉到一些外部狀態(tài),例如:函數(shù)被創(chuàng)建時(shí)的狀態(tài)。

另一種表示方式為:一個(gè)閉包繼承了 函數(shù)所聲明時(shí)的作用域灼狰。這種狀態(tài)(作用域內(nèi)的變量)都被共享到閉包的環(huán)境中袱瓮,因此這些變量可以在 閉包中被操作缤骨,直到被銷毀。閉包經(jīng)常被用作包裝函數(shù):它們會(huì)預(yù)先定義好 1 個(gè)或多個(gè)參數(shù)以用于包 裝尺借。另一個(gè)不錯(cuò)的應(yīng)用就是使用閉包來(lái)完成更加簡(jiǎn)潔的錯(cuò)誤檢查荷憋。

僅僅從形式上將閉包簡(jiǎn)單理解為匿名函數(shù)是不夠的,還需要理解閉包實(shí)質(zhì)上的含義褐望。

實(shí)質(zhì)上看,閉包是由函數(shù)及其相關(guān)引用環(huán)境組合而成的實(shí)體(即:閉包=函數(shù)+引用環(huán)境)串前。閉包在運(yùn)行時(shí) 可以有多個(gè)實(shí)例瘫里,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實(shí)例。由閉包的實(shí)質(zhì)含義荡碾,我們可 以推論:閉包獲取捕獲變量相當(dāng)于引用傳遞谨读,而非值傳遞;對(duì)于閉包函數(shù)捕獲的常量和變量坛吁,無(wú)論閉包 何時(shí)何處被調(diào)用劳殖,閉包都可以使用這些常量和變量,而不用關(guān)心它們表面上的作用域拨脉。

引用環(huán)境驗(yàn)證

package main

import "fmt"

func addNumber(x int) func(int) {
    fmt.Printf("x :%d addr of x:%p\n", x, &x)
    return func(y int) {
        k := x + y
        x = k
        y = k
        fmt.Printf("x :%d addr of x:%p\n", x, &x)
        fmt.Printf("y :%d addr of y:%p\n", y, &y)
    }
}

func main() {
    addNum := addNumber(5)
    addNum(1)
    addNum(1)
    addNum(1)
    fmt.Println("-------------------------------")
    addNum2 := addNumber(5)
    addNum2(1)
    addNum2(1)
    addNum2(2)
}

output:

x :5 addr of x:0xc00000a0c8
x :6 addr of x:0xc00000a0c8
y :6 addr of y:0xc00000a110
x :7 addr of x:0xc00000a0c8
y :7 addr of y:0xc00000a128
x :8 addr of x:0xc00000a0c8
y :8 addr of y:0xc00000a140
-------------------------------
x :5 addr of x:0xc00000a158
x :6 addr of x:0xc00000a158
y :6 addr of y:0xc00000a168
x :7 addr of x:0xc00000a158
y :7 addr of y:0xc00000a180
x :9 addr of x:0xc00000a158
y :9 addr of y:0xc00000a198

根據(jù)上面代碼結(jié)果哆姻,發(fā)現(xiàn)X在匿名函數(shù)聲明時(shí)傳入,是引用該參數(shù)玫膀。后續(xù)調(diào)用同一個(gè)匿名函數(shù)x地址不變矛缨,但值會(huì)改變。而y值作為匿名函數(shù)參數(shù)每次調(diào)用都傳值帖旨,地址在改變箕昭。

斐波那契數(shù)


import "fmt"

func test(a, b int) func() int {
    return func() int {
        a, b = b, a+b
        return a
    }
}

func main() {
    var a, b int = 1, 1
    c := test(a, b)
    for i := 0; i < 10; i++ {
        fmt.Println(c())
    }
}

output:

1
2
3
5
8
13
21
34
55
89

使用閉包調(diào)試:

方法1:
當(dāng)您在分析和調(diào)試復(fù)雜的程序時(shí),無(wú)數(shù)個(gè)函數(shù)在不同的代碼文件中相互調(diào)用解阅,如果這時(shí)候能夠準(zhǔn)確地知 道哪個(gè)文件中的具體哪個(gè)函數(shù)正在執(zhí)行落竹,對(duì)于調(diào)試是十分有幫助的。您可以使用 runtime 或 log 包 中的特殊函數(shù)來(lái)實(shí)現(xiàn)這樣的功能货抄。包 runtime 中的函數(shù) Caller() 提供了相應(yīng)的信息述召,因此可以在 需要的時(shí)候?qū)崿F(xiàn)一個(gè) where() 閉包函數(shù)來(lái)打印函數(shù)執(zhí)行的位置:

package main

import (
    "fmt"
    "runtime"
)

func main() {
    where := func() {
        _, file, line, _ := runtime.Caller(1)
        fmt.Printf("%s:%d\n", file, line)
    }
    where()
    fmt.Println("---next---")
    where()
}

output:

H:/awesomeProject/foo/go42.go:13
---next---
H:/awesomeProject/foo/go42.go:15

方法2:
使用log包的打印函數(shù)

package main

import (
  "fmt"
  "log"
)

func main() {
  log.SetFlags(log.Llongfile | log.LstdFlags)
  where := log.Print
  where()
  fmt.Println("---next---")
  where()
}

output:

2020/10/12 21:46:44 H:/awesomeProject/foo/go42.go:11: 
---next---
2020/10/12 21:46:44 H:/awesomeProject/foo/go42.go:13: 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟹地,隨后出現(xiàn)的幾起案子桨武,更是在濱河造成了極大的恐慌,老刑警劉巖锈津,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呀酸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡琼梆,警方通過(guò)查閱死者的電腦和手機(jī)性誉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門窿吩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人错览,你說(shuō)我怎么就攤上這事纫雁。” “怎么了倾哺?”我有些...
    開(kāi)封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵轧邪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我羞海,道長(zhǎng)忌愚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任却邓,我火速辦了婚禮硕糊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腊徙。我一直安慰自己简十,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布撬腾。 她就那樣靜靜地躺著螟蝙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪民傻。 梳的紋絲不亂的頭發(fā)上胶逢,一...
    開(kāi)封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音饰潜,去河邊找鬼初坠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛彭雾,可吹牛的內(nèi)容都是我干的碟刺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼薯酝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼半沽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吴菠,我...
    開(kāi)封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤者填,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后做葵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體占哟,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了榨乎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怎燥。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蜜暑,靈堂內(nèi)的尸體忽然破棺而出铐姚,到底是詐尸還是另有隱情,我是刑警寧澤肛捍,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布隐绵,位于F島的核電站,受9級(jí)特大地震影響拙毫,放射性物質(zhì)發(fā)生泄漏依许。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一恬偷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帘睦,春花似錦袍患、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至古胆,卻和暖如春肆良,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逸绎。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工惹恃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棺牧。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓巫糙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親颊乘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子参淹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355