在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是閉包的延遲綁定

馬哥Linux運(yùn)維 ? 來(lái)源:馬哥Linux運(yùn)維 ? 作者:馬哥Linux運(yùn)維 ? 2022-09-02 10:39 ? 次閱讀

本文講介紹以下幾個(gè)內(nèi)容:

引入用GoLang語(yǔ)言寫(xiě)的幾個(gè)case;

介紹什么是閉包;

介紹什么是閉包的延遲綁定;

從閉包的延遲綁定講到GoLang的Go Routine的延遲綁定問(wèn)題;

I. 幾個(gè)有趣的Case

開(kāi)門見(jiàn)山,首先請(qǐng)各位看官們先看下面foo1()到foo7()一共7個(gè)函數(shù),然后回答后面的問(wèn)題。(一下子丟出7個(gè)函數(shù),請(qǐng)見(jiàn)諒。不過(guò),每個(gè)函數(shù)都非常簡(jiǎn)短,而本文接下來(lái)將圍繞這7個(gè)函數(shù)展開(kāi),因此,請(qǐng)各位看官老爺們耐心且看看題,活動(dòng)活動(dòng)腦細(xì)胞~)

case 1:


func foo1(x *int) func() {  return func() {    *x = *x + 1    fmt.Printf("foo1 val = %d
", *x)  }}
case 2:

func foo2(x int) func() {  return func() {    x = x + 1    fmt.Printf("foo2 val = %d
", x)  }}
case 3:

func foo3() {  values := []int{1, 2, 3, 5}  for _, val := range values {    fmt.Printf("foo3 val = %d
", val)  }}
case 4:

func show(v interface{}) {  fmt.Printf("foo4 val = %v
", v)}func foo4() {  values := []int{1, 2, 3, 5}  for _, val := range values {    go show(val)  }}
case 5:

func foo5() {  values := []int{1, 2, 3, 5}  for _, val := range values {    go func() {      fmt.Printf("foo5 val = %v
", val)    }()  }}
case 6:

var foo6Chan = make(chan int, 10)func foo6() {  for val := range foo6Chan {    go func() {      fmt.Printf("foo6 val = %d
", val)    }()  }}
case 7:

func foo7(x int) []func() {  var fs []func()  values := []int{1, 2, 3, 5}  for _, val := range values {    fs = append(fs, func() {      fmt.Printf("foo7 val = %d
", x+val)    })  }  return fs}

Q1:

第一組實(shí)驗(yàn):假設(shè)現(xiàn)在有變量x=133,并創(chuàng)建變量f1和f2分別為foo1(&x)和foo2(x)的返回值,請(qǐng)問(wèn)多次調(diào)用f1()和f2()會(huì)打印什么?

第二組實(shí)驗(yàn):重新賦值變量x=233,請(qǐng)問(wèn)此時(shí)多次調(diào)用f1()和f2()會(huì)打印什么?

第三組實(shí)驗(yàn):如果直接調(diào)用foo1(&x)()和foo2(x)()多次,請(qǐng)問(wèn)每次都會(huì)打印什么?

Q2:
請(qǐng)問(wèn)分別調(diào)用函數(shù)foo3(),foo4()和foo5(),分別會(huì)打印什么?

Q3:

第一組實(shí)驗(yàn):如果“幾乎同時(shí)”往channelfoo6Chan里面塞入一組數(shù)據(jù)"1,2,3,5",foo6會(huì)打印什么?

第二組實(shí)驗(yàn):如果以間隔納秒(10^-9秒)的時(shí)間往channel里面塞入一組數(shù)據(jù),此時(shí)foo6又會(huì)打印什么?

第三組實(shí)驗(yàn):如果是微秒(10^-6秒)呢?如果是毫秒(10^-3秒)呢?如果是秒呢?

Q4:
請(qǐng)問(wèn)如果創(chuàng)建變量f7s=foo7(11),f7s是一個(gè)函數(shù)集合,遍歷f7s會(huì)打印什么?

接下來(lái),我們逐一來(lái)看這些問(wèn)題和對(duì)應(yīng)的foo函數(shù)。

II. case1~2:值傳遞(by value) vs. 引用傳遞(by reference)

子標(biāo)題好難起 >0<... ? 看到case1和case2的兩組函數(shù)foo1()和foo2(),相信各位看官就知道,其中一個(gè)知識(shí)點(diǎn)就是值傳遞和引用傳遞。 ? 其實(shí)呢,Go是沒(méi)有引用傳遞的,即使是foo1()在參數(shù)上加了*,內(nèi)部實(shí)現(xiàn)機(jī)制仍舊是值傳遞,只不過(guò)傳遞的是指針的數(shù)值。但是為了稱呼方便,下文會(huì)成為“引用傳遞”(為了區(qū)分正確的引用傳遞,這里特意加了引號(hào))。 ? 如下圖所示,我們的目的是傳遞X變量,于是我們創(chuàng)建了一個(gè)傳參地址(臨時(shí)地址變量),它存放了X變量的地址值,調(diào)用函數(shù)的時(shí)候給它這個(gè)傳參地址,函數(shù)呢,則會(huì)再創(chuàng)建一個(gè)入?yún)⒌刂罚莻鲄⒌刂返囊环菘截悺:瘮?shù)拿到了這個(gè)地址值,可以通過(guò)尋址拿到這個(gè)X變量,此時(shí)函數(shù)如果直接修改X變量可以認(rèn)為是“本地修改”或者“永久修改”了這個(gè)變量的數(shù)值。 ? 「舉個(gè)生活中的例子,比如一個(gè)叫做“函數(shù)”的人想尋找一個(gè)叫做“X”的人,函數(shù)跑過(guò)來(lái)問(wèn)知道X的我,我拿出地址簿,給他出示了X這個(gè)人的家庭地址,函數(shù)記性不太好,所以拿了一本本子把X的地址抄在了他自己的本子上。」 ? 這個(gè)例子中,我的那個(gè)記著X的家庭地址的地址簿,就是傳參地址;函數(shù)抄錄了X地址的本子,就是入?yún)⒌刂罚籜的家庭地址,就對(duì)應(yīng)了X變量的地址值。(哎,為什么講的這么細(xì)節(jié)了?) 2e5dc4ec-2a04-11ed-ba43-dac502259ad0.jpg ? Golang的“引用傳遞” ? 話題似乎有點(diǎn)扯遠(yuǎn)了,拉回來(lái),我們?cè)賮?lái)看看foo1()和foo2()。 ? foo1()和foo2()的區(qū)別確實(shí)在于值傳遞和引用傳遞,但是這個(gè)并不是本文介紹的中心。本文要介紹的已經(jīng)在標(biāo)題上寫(xiě)明了:閉包(closure)。 ?

閉包(closure)

什么是閉包呢?摘用Wikipedia上的一句定義:

aclosureis a record storinga functiontogether withan environment.
閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體 。

因此閉包的核心就是:函數(shù)和環(huán)境。其實(shí)這里就已經(jīng)可以回答本文題目的問(wèn)題:閉包究竟包了什么?答案是:函數(shù)和環(huán)境。但是相信部分看官們到這里依然不清楚:什么函數(shù)?什么環(huán)境? 函數(shù),指的是在閉包實(shí)際實(shí)現(xiàn)的時(shí)候,往往通過(guò)調(diào)用一個(gè)外部函數(shù)返回其內(nèi)部函數(shù)來(lái)實(shí)現(xiàn)的。內(nèi)部函數(shù)可能是內(nèi)部實(shí)名函數(shù)、匿名函數(shù)或者一段lambda表達(dá)式。用戶得到一個(gè)閉包,也等同于得到了這個(gè)內(nèi)部函數(shù),每次執(zhí)行這個(gè)閉包就等同于執(zhí)行內(nèi)部函數(shù)。 環(huán)境,Wikipedia上說(shuō)是與其(函數(shù))相關(guān)的引用環(huán)境,可以說(shuō)解釋地很精準(zhǔn)了。 具體地說(shuō),在實(shí)際中引用環(huán)境是指外部函數(shù)的環(huán)境,閉包保存/記錄了它產(chǎn)生時(shí)的外部函數(shù)的所有環(huán)境。但是這段話對(duì)于尚未理解閉包的同學(xué)來(lái)說(shuō)依舊是不友好的,聽(tīng)完還是懵懂的。這里嘗試做個(gè)更實(shí)用性的解釋:

如果外部函數(shù)的所有變量可見(jiàn)性都是local的,即生命周期在外部函數(shù)結(jié)束時(shí)也結(jié)束的,那么閉包的環(huán)境也是封閉的。

反之,那么閉包其實(shí)不再封閉,全局可見(jiàn)的變量的修改,也會(huì)對(duì)閉包內(nèi)的這個(gè)變量造成影響。

跳回foo1()和foo2()的例子,正好來(lái)解釋閉包的函數(shù)和環(huán)境。


func foo1(x *int) func() {    return func() {        *x = *x + 1        fmt.Printf("foo1 val = %d
", *x)    }}func foo2(x int) func() {    return func() {        x = x + 1        fmt.Printf("foo1 val = %d
", x)    }}
// Q1第一組實(shí)驗(yàn)x := 133f1 := foo1(&x)f2 := foo2(x)f1() f2()f1()f2()// Q1第二組x = 233f1()f2()f1()f2()// Q1第三組foo1(&x)()foo2(x)()foo1(&x)()foo2(x)()
定義了x=133之后,我們獲取得到了f1=foo1(&x)和f2=foo2(x)。這里f1f2就是閉包的函數(shù),也就是foo1()foo2()的內(nèi)部匿名函數(shù);而閉包的環(huán)境即外部函數(shù)foo1()foo2()的變量x(因?yàn)閮?nèi)部匿名函數(shù)引用到的相關(guān)變量只有x,因此這里簡(jiǎn)化為變量x)。 閉包的函數(shù)做的事情歸納為:1). 將環(huán)境的變量x自增1;2). 打印環(huán)境變量x。 閉包的環(huán)境則是其外部函數(shù)獲取到的變量x。 因此Q1第一組實(shí)驗(yàn)的答案為:

f1() // foo1 val = 134f2() // foo2 val = 134f1() // foo1 val = 135f2() // foo2 val = 135
這是因?yàn)殚]包f1f2都保存了x=133時(shí)的整個(gè)環(huán)境,每次調(diào)用閉包f1f2都會(huì)執(zhí)行一次自增+打印的內(nèi)部匿名函數(shù)。因此第一次輸出都是(133+1=)134,第二次輸出都是(134+1=)135。 那么Q1第二組實(shí)驗(yàn)的答案呢?

f1() // foo1 val = 234f2() // foo2 val = 136f1() // foo1 val = 235f2() // foo2 val = 137
有趣的事情發(fā)生了!f1的值居然發(fā)生了顯著性的變化!通過(guò)這組實(shí)驗(yàn),能夠更好地解釋其(函數(shù))相關(guān)的引用環(huán)境其實(shí)就是產(chǎn)生這個(gè)閉包的時(shí)候的外部函數(shù)的環(huán)境,因此變量x的可見(jiàn)性和作用域也與外部函數(shù)相同,又因?yàn)閒oo1是“引用傳遞”,變量x的作用域不局限在foo1()中,因此當(dāng)x發(fā)生變化的時(shí)候,閉包f1內(nèi)部也變化了。這個(gè)也正好是"反之,那么閉包其實(shí)不再封閉,全局可見(jiàn)的變量的修改,也會(huì)對(duì)閉包內(nèi)的這個(gè)變量造成影響"的證明。 Q1的第三組實(shí)驗(yàn)的答案:

foo1(&x)() // foo1 val = 236foo2(x)() // foo2 val = 237foo1(&x)() // foo1 val = 237foo2(x)() // foo2 val = 238foo2(x)() // foo2 val = 238
因?yàn)閒oo1()返回的閉包都會(huì)修改變量x的數(shù)值,因此調(diào)用foo1()()之后,變量x必然增加1。而foo2()返回的閉包僅僅修改其內(nèi)部環(huán)境的變量x而對(duì)調(diào)用外部的變量x不影響,且每次調(diào)用foo2()返回的閉包是獨(dú)立的,和其他調(diào)用foo2()的閉包不相關(guān),因此最后兩次的調(diào)用,打印的數(shù)值都是相同的;第一次調(diào)用和第二次調(diào)用foo2()發(fā)現(xiàn)打印出來(lái)的數(shù)值增加了1,是因?yàn)閮纱握{(diào)用之間傳入的x的數(shù)值分別是236和237,而不是說(shuō)第二次在第一次基礎(chǔ)上增加了1,這點(diǎn)需要補(bǔ)充說(shuō)明。

III. case7:閉包的延遲綁定

hhh,是不是以為我會(huì)接著講case3,居然先提到了case7,意不意外驚不驚喜! 廢話不多說(shuō),看官們來(lái)瞅瞅下面調(diào)用f7()的時(shí)候分別會(huì)打印什么?


func foo7(x int) []func() {    var fs []func()    values := []int{1, 2, 3, 5}    for _, val := range values {        fs = append(fs, func() {            fmt.Printf("foo7 val = %d
", x+val)        })    }    return fs}// Q4實(shí)驗(yàn):f7s := foo7(11)for _, f7 := range f7s {    f7()}
答案是:

foo7 val = 16foo7 val = 16foo7 val = 16foo7 val = 16
是的,你沒(méi)有看錯(cuò),會(huì)打印4行,且都是16!是不是很驚喜! 相信已經(jīng)有很多同學(xué)在網(wǎng)上看到過(guò)類似的case,并且也早已知道結(jié)果了,不清楚的同學(xué)們現(xiàn)在也看到答案了。嗯,這就是大名鼎鼎的閉包延遲綁定問(wèn)題。網(wǎng)上的解釋其實(shí)有很多了,這里嘗試用之前對(duì)于閉包的環(huán)境的定義來(lái)解釋這個(gè)現(xiàn)象: “ 閉包是一段函數(shù)和相關(guān)的引用環(huán)境的實(shí)體。case7的問(wèn)題中,函數(shù)是打印變量val的值,引用環(huán)境是變量val。僅僅是這樣的話,遍歷到val=1的時(shí)候,記錄的不應(yīng)該是val=1的環(huán)境嗎? 上文在閉包解釋最后,還有一句話:閉包保存/記錄了它產(chǎn)生時(shí)的外部函數(shù)的所有環(huán)境。如同普通變量/函數(shù)的定義和實(shí)際賦值/調(diào)用或者說(shuō)執(zhí)行,是兩個(gè)階段。閉包也是一樣,for-loop內(nèi)部?jī)H僅是聲明了一個(gè)閉包,foo7()返回的也僅僅是一段閉包的函數(shù)定義,只有在外部執(zhí)行了f7()時(shí)才真正執(zhí)行了閉包,此時(shí)才閉包內(nèi)部的變量才會(huì)進(jìn)行賦值的操作。哎,如果這么說(shuō)的話,豈不是應(yīng)該拋出異常嗎?因?yàn)関al是一個(gè)比f(wàn)oo7()生命周期更短的變量啊? 這就是閉包的神奇之處,它會(huì)保存相關(guān)引用的環(huán)境,也就是說(shuō),val這個(gè)變量在閉包內(nèi)的生命周期得到了保證。因此在執(zhí)行這個(gè)閉包的時(shí)候,會(huì)去外部環(huán)境尋找最新的數(shù)值!你是不是不相信?來(lái)來(lái)來(lái),我們馬上寫(xiě)個(gè)臨時(shí)的case執(zhí)行下分分鐘就明白了:

臨時(shí)的case:


func foo0() func() {    x := 1    f := func() {        fmt.Printf("foo0 val = %d
", x)    }    x = 11    return f}
foo0()() // 猜猜我會(huì)輸出什么?
既然我說(shuō)會(huì)在執(zhí)行的時(shí)候去外部環(huán)境尋找最新的數(shù)值,那x的最新數(shù)值就是11呀,果然,最后輸出的就是11。 以上就是我對(duì)于閉包的延遲綁定的通俗版本解釋。:)

IV. case3~6:Go Routine的延遲綁定

case3、case4和case5不是閉包,case3只是遍歷了內(nèi)部的slice并且打印,case4是在遍歷時(shí)通過(guò)協(xié)程調(diào)用了打印函數(shù)打印,case5也是在遍歷slice時(shí)調(diào)用了內(nèi)部匿名函數(shù)打印。 Q2的case3問(wèn)題的答案先丟出來(lái):


func foo3() {    values := []int{1, 2, 3, 5}    for _, val := range values {        fmt.Printf("foo3 val = %d
", val)    }}
foo3()//foo3 val = 1a//foo3 val = 2//foo3 val = 3//foo3 val = 5
中規(guī)中矩,遍歷輸出slice的內(nèi)容:1,2,3,5。 Q2的case4問(wèn)題的答案再丟出來(lái):

func show(v interface{}) {    fmt.Printf("foo4 val = %v
", v)}func foo4() {    values := []int{1, 2, 3, 5}    for _, val := range values {        go show(val)    }}
foo4()//foo3 val = 2//foo3 val = 3//foo3 val = 1//foo3 val = 5
嗯,因?yàn)镚o Routine的執(zhí)行順序是隨機(jī)并行的,因此執(zhí)行多次foo4()輸出的順序不一行相同,但是一定打印了“1,2,3,5”各個(gè)元素。 最后是Q2的case5問(wèn)題的答案:

func foo5() {    values := []int{1, 2, 3, 5}    for _, val := range values {        go func() {            fmt.Printf("foo5 val = %v
", val)        }()    }}
foo5()//foo3 val = 5//foo3 val = 5//foo3 val = 5//foo3 val = 5
居然都打印了5,驚不驚喜,意不意外?!相信看過(guò)子標(biāo)題的你,一定不意外了(捂臉)。是的,接下來(lái)就要講講Go Routine的延遲綁定: 其實(shí)這個(gè)問(wèn)題的本質(zhì)同閉包的延遲綁定,或者說(shuō),這段匿名函數(shù)的對(duì)象就是閉包。在我們調(diào)用go func() { xxx }()的時(shí)候,只要沒(méi)有真正開(kāi)始執(zhí)行這段代碼,那它還只是一段函數(shù)聲明。而在這段匿名函數(shù)被執(zhí)行的時(shí)候,才是內(nèi)部變量尋找真正賦值的時(shí)候。 在case5中,for-loop的遍歷幾乎是“瞬時(shí)”完成的,4個(gè)Go Routine真正被執(zhí)行在其后。矛盾是不是產(chǎn)生了?這個(gè)時(shí)候for-loop結(jié)束了呀,val生命周期早已結(jié)束了,程序應(yīng)該報(bào)錯(cuò)才對(duì)呀? 回憶上一章,是不是一個(gè)相同的情境?是的,這個(gè)匿名函數(shù)可不就是一個(gè)閉包嗎?一切就解釋通了:閉包真正被執(zhí)行的時(shí)候,for-loop結(jié)束了,但是val的生命周期在閉包內(nèi)部被延長(zhǎng)了且被賦值到最新的數(shù)值5。 不知道各位看官是否好奇,既然說(shuō)Go Routine執(zhí)行的時(shí)候比f(wàn)or-loop慢,那如果我在遍歷的時(shí)候增加sleep機(jī)制呢?于是設(shè)計(jì)了Q3實(shí)驗(yàn):

var foo6Chan = make(chan int, 10)func foo6() {    for val := range foo6Chan {        go func() {            fmt.Printf("foo6 val = %d
", val)        }()    }}// Q3第一組實(shí)驗(yàn)go foo6()foo6Chan <- 1foo6Chan <- 2foo6Chan <- 3foo6Chan <- 5// Q3第二組實(shí)驗(yàn)foo6Chan <- 11time.Sleep(time.Duration(1) * time.Nanosecond)foo6Chan <- 12time.Sleep(time.Duration(1) * time.Nanosecond)foo6Chan <- 13time.Sleep(time.Duration(1) * time.Nanosecond)foo6Chan <- 15// Q3第三組實(shí)驗(yàn)// 微秒foo6Chan <- 21time.Sleep(time.Duration(1) * time.Microsecond)foo6Chan <- 22time.Sleep(time.Duration(1) * time.Microsecond)foo6Chan <- 23time.Sleep(time.Duration(1) * time.Microsecond)foo6Chan <- 25time.Sleep(time.Duration(10) * time.Second)// 毫秒foo6Chan <- 31time.Sleep(time.Duration(1) * time.Millisecond)foo6Chan <- 32time.Sleep(time.Duration(1) * time.Millisecond)foo6Chan <- 33time.Sleep(time.Duration(1) * time.Millisecond)foo6Chan <- 35time.Sleep(time.Duration(10) * time.Second)// 秒foo6Chan <- 41time.Sleep(time.Duration(1) * time.Second)foo6Chan <- 42time.Sleep(time.Duration(1) * time.Second)foo6Chan <- 43time.Sleep(time.Duration(1) * time.Second)foo6Chan <- 45time.Sleep(time.Duration(10) * time.Second)// 實(shí)驗(yàn)完畢,最后記得關(guān)閉channelclose(foo6Chan)
嘗試執(zhí)行了多次,第一組答案如下:

foo6 val = 5/3foo6 val = 5foo6 val = 5foo6 val = 5
絕大部分時(shí)候執(zhí)行出來(lái)都是5。 第二組答案如下:

foo6 val = 15/13/11/12foo6 val = 15/13foo6 val = 15foo6 val = 15
絕大部分時(shí)候執(zhí)行得到的都是15。 第三組答案如下:

// 微秒foo6 val = 23/21foo6 val = 23/22foo6 val = 25/23foo6 val = 25// 毫秒foo6 val = 31foo6 val = 32foo6 val = 33foo6 val = 35// 秒foo6 val = 41foo6 val = 42foo6 val = 43foo6 val = 45
毫秒和秒的兩組非常確定,順序輸出。但是微妙就不一定了,有時(shí)候是順序輸出,大部分時(shí)候是隨機(jī)輸出如“22,22,23,25”或者“21,22,25,25”之類的。 可見(jiàn),Go Routine的匿名函數(shù)從定義到執(zhí)行,耗時(shí)時(shí)間在微妙上下。于是又增加了一個(gè)臨時(shí)的case測(cè)試了其真正的耗時(shí)大約是多少。

又一個(gè)臨時(shí)的case:


func foo8() {    for i := 1; i < 10; i++ {        curTime := time.Now().UnixNano()        go func(t1 int64) {            t2 := time.Now().UnixNano()            fmt.Printf("foo8 ts = %d us 
", t2-t1)        }(curTime)    }}
foo8()
執(zhí)行下來(lái)發(fā)現(xiàn)耗時(shí)在5微秒~60微秒之間不等。 但是,以上的實(shí)驗(yàn)數(shù)據(jù)都是從我的iMac本子上得到的,該本子的CPU是i7-7700K 4.2GHz;我又放在筆記本上(CPU為i5-8250U 1.6GHz 1.8GHz)運(yùn)行了下,發(fā)現(xiàn)居然耗時(shí)是0微秒!起初我懷疑是時(shí)間精度的問(wèn)題,于是把t1和t2時(shí)間都打印出來(lái),精度是可以達(dá)到納秒的。抱著仍舊不信的想法,重新運(yùn)行了第三組實(shí)驗(yàn),每一個(gè)都是順序輸出的! 好吧,回頭再說(shuō)我的iMac的問(wèn)題。現(xiàn)在只需要記住一點(diǎn):Go Routine的匿名函數(shù)的延遲綁定本質(zhì)就是閉包,實(shí)際生成中注意下這種寫(xiě)法~

寫(xiě)在后面

最后,閉包是個(gè)常見(jiàn)的玩意兒,但是實(shí)際代碼中不太建議使用,一不小心寫(xiě)了個(gè)內(nèi)存泄漏查都查不到。特別是不要為了炫技故意寫(xiě)個(gè)閉包,實(shí)在沒(méi)有必要。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7085

    瀏覽量

    89217
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4338

    瀏覽量

    62767
  • 閉包
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    2070

原文標(biāo)題:Golang:“閉包(closure)”到底包了什么?

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux內(nèi)核驅(qū)動(dòng)與單個(gè)PCI設(shè)備的綁定和解綁定

    在Linux內(nèi)核2.6.13-rc3以前,驅(qū)動(dòng)和設(shè)備之間的綁定和解綁只能通過(guò)insmod(modprobe)和rmmod來(lái)實(shí)現(xiàn),但是這種實(shí)現(xiàn)方法有一個(gè)弊端,就是一旦綁定或者解綁定都是針對(duì)驅(qū)動(dòng)與其
    的頭像 發(fā)表于 11-17 17:11 ?1698次閱讀
    Linux內(nèi)核驅(qū)動(dòng)與單個(gè)PCI設(shè)備的<b class='flag-5'>綁定</b>和解<b class='flag-5'>綁定</b>

    綁定”成功后,請(qǐng)問(wèn)怎么通過(guò)綁定的設(shè)備向被綁定的設(shè)備發(fā)送控制命令?

    。抓都正常響應(yīng)了響應(yīng)的respone。但是,我不知道怎么通過(guò)綁定的設(shè)備向被綁定的設(shè)備發(fā)送控制命令。比如,一個(gè)開(kāi)關(guān)和燈實(shí)現(xiàn)了綁定,這個(gè)綁定
    發(fā)表于 05-22 00:08

    詞法作用域和

    #hello,JS:14(詞法作用域)
    發(fā)表于 05-20 15:35

    ECMAScript的與匿名函數(shù)你分的清嗎?

    重拾ECMAScript基礎(chǔ)——與匿名函數(shù)
    發(fā)表于 11-08 09:39

    javascript是什么_javascript有什么作用

    首先從一個(gè)經(jīng)典錯(cuò)誤談起,頁(yè)面上有若干個(gè)div, 我們想給它們綁定一個(gè)onclick方法,于是有了下面的代碼很簡(jiǎn)單的功能可是卻偏偏出錯(cuò)了,每次alert出的值都是簡(jiǎn)單的修改就好使了讓我們從一些基礎(chǔ)的知識(shí)談起,首先了解一下內(nèi)部函數(shù)。
    發(fā)表于 12-05 10:40 ?1796次閱讀
    javascript<b class='flag-5'>閉</b><b class='flag-5'>包</b>是什么_javascript<b class='flag-5'>閉</b><b class='flag-5'>包</b>有什么作用

    javascript原理及應(yīng)用

    官方對(duì)的解釋是:一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該表達(dá)式的一部分。作為一個(gè)函數(shù)變量的一個(gè)引用,當(dāng)函數(shù)返回時(shí),其處于激活狀態(tài)。
    發(fā)表于 12-05 10:55 ?1226次閱讀
    javascript<b class='flag-5'>閉</b><b class='flag-5'>包</b>原理及應(yīng)用

    javascript的優(yōu)缺點(diǎn)有哪些

    是javascript的一大難點(diǎn),也是它的特色。很多高級(jí)應(yīng)用都要依靠來(lái)實(shí)現(xiàn)。要理解
    發(fā)表于 12-05 11:10 ?9351次閱讀

    用最簡(jiǎn)單的語(yǔ)言解釋Python的是什么?

    很藍(lán)瘦,你應(yīng)該盡量理解一下它。
    的頭像 發(fā)表于 03-21 16:33 ?2124次閱讀

    詳細(xì)介紹go語(yǔ)言中的的實(shí)現(xiàn)

    什么是? 什么場(chǎng)景下會(huì)用 ? 本文對(duì) go 語(yǔ)言中的做了詳細(xì)介紹。
    的頭像 發(fā)表于 10-20 16:18 ?1869次閱讀

    帶你了解go語(yǔ)言中的

    ? 【 導(dǎo)讀】什么是? 什么場(chǎng)景下會(huì)用 ? 本文對(duì) go 語(yǔ)言中的做了詳細(xì)介紹。
    的頭像 發(fā)表于 11-02 15:27 ?2461次閱讀

    無(wú)縫綁定和非綁定支持

    自動(dòng)獲取并同步來(lái)自任何應(yīng)用程序的綁定數(shù)據(jù)。NET源代碼,包括交錯(cuò)數(shù)組、任何實(shí)現(xiàn)IListSource或IList的對(duì)象,以及任何ADO。NET數(shù)據(jù)集、DataTable、DataView或DataViewManager對(duì)象。
    的頭像 發(fā)表于 01-30 15:26 ?472次閱讀

    教程 5:配對(duì)、綁定和安全

    教程 5:配對(duì)、綁定和安全
    發(fā)表于 03-15 19:39 ?0次下載
    教程 5:配對(duì)、<b class='flag-5'>綁定</b>和安全

    教程 5:配對(duì)、綁定和安全

    教程 5:配對(duì)、綁定和安全
    發(fā)表于 07-06 18:49 ?0次下載
    教程 5:配對(duì)、<b class='flag-5'>綁定</b>和安全

    Rust語(yǔ)言中的應(yīng)用場(chǎng)景

    Rust語(yǔ)言的是一種可以捕獲外部變量并在需要時(shí)執(zhí)行的匿名函數(shù)。包在Rust中是一等公民,它們可以像其他變量一樣傳遞、存儲(chǔ)和使用。
    的頭像 發(fā)表于 09-20 11:25 ?614次閱讀

    工業(yè)交換機(jī)的零延遲和零丟

    在現(xiàn)代工業(yè)自動(dòng)化和網(wǎng)絡(luò)通信的快速發(fā)展中,工業(yè)交換機(jī)作為連接各類設(shè)備的核心元素,其性能和穩(wěn)定性顯得尤為重要。零延遲和零丟的概念不僅是技術(shù)上的追求,更是推動(dòng)工業(yè)智能化進(jìn)程的重要保障。傳統(tǒng)網(wǎng)絡(luò)在數(shù)
    的頭像 發(fā)表于 09-24 15:52 ?238次閱讀
    主站蜘蛛池模板: 欧美3d动漫网站| 日本wwwwww| 亚洲国产欧美在线人成aaa| 女bbwxxxx非洲黑人| 中文字幕区| 国产叼嘿免费视频网站| 伊人狠狠丁香婷婷综合色| 亚洲香蕉网久久综合影院3p| 五月婷六月婷婷| 日韩一区二区在线观看| 免费观看黄色在线视频| 国产色女人| 天天色天天操天天| 亚洲国产成人成上人色| 亚洲mv在线观看| 欧美亚洲综合一区| 五月.com| 欧美香蕉在线| 国产人成精品香港三级古代| 99久久综合精品免费| 天天插天天操| 在线播放视频网站| 欧美日本免费| 天天噜噜色| 久久综合香蕉久久久久久久| 国产成人毛片毛片久久网| 天天干天天弄| 欧美性猛| 亚洲开心激情网| 欧美日韩生活片| 最近最新中文字幕在线第一页| 日操夜操天天操| 天天爽天天干| 免费看h网站| 亚洲综合成人网| 美日韩免费视频| 你懂的亚洲| www日本黄色| 国产人人看| 抽搐一进一出gif免费男男| 日韩欧美中文字幕在线播放|