语言中拟合函数 计算aic_Go语言函数深度解析(中)
上回函數(shù)深度解析給大家聊了一些函數(shù)的基本知識,不知道還有沒有人記得,不記得趕緊回去復(fù)習(xí)!
他們是
- go語言中函數(shù)的基本原理
- 單/多個(gè)同/不同類型參數(shù)
- 單/多個(gè)同/不同類型返回值
- 值傳遞,引用傳遞
- 函數(shù)進(jìn)階,把函數(shù)當(dāng)作變量傳遞(在不改變函數(shù)內(nèi)部結(jié)構(gòu)的情況下傳入新的實(shí)現(xiàn))
匿名函數(shù)
話不多說,今天小熊就帶各位家人感受下go語言函數(shù)中的高級語法。
在前面的文章里我們學(xué)會(huì)了把函數(shù)當(dāng)作變量傳遞,可以在不改動(dòng)原有函數(shù)內(nèi)部實(shí)現(xiàn)的情況下,改變函數(shù)實(shí)現(xiàn)細(xì)節(jié)(設(shè)計(jì)模式:裝飾器)。
這種情況下的作為變量傳遞的函數(shù)往往只有這一個(gè)地方用到了,其他地方不會(huì)重復(fù)使用。那就沒必要單獨(dú)定義一個(gè)函數(shù)在外面!(多此一舉的事本熊不做!)
like this:
func?functionValue(a,?b?int,????do?func(int,?int)?int)?{
?fmt.Println(do(a,?b))
}
//使用匿名函數(shù)的方法調(diào)用他?實(shí)現(xiàn)匿名加函數(shù)
funcationValue(1,2,func(a,b?int)?int{
return?a+b?})
//使用匿名函數(shù)的方法調(diào)用他?實(shí)現(xiàn)匿名減函數(shù)
funcationValue(1,2,func(a,b?int)?int{
return?a-b?})
在調(diào)用的時(shí)候我們才實(shí)現(xiàn)了一個(gè)匿名函數(shù)(沒有名字的函數(shù))
那是不是只有把函數(shù)當(dāng)變量傳遞的時(shí)候才用到匿名函數(shù)呢?并,不,是!
各位同學(xué),讓我上黑板給大家實(shí)現(xiàn)一個(gè)簡單的匿名函數(shù)用法。
f?:=?func(i?int)?{??fmt.Println(i)
?}
f(1)
把匿名函數(shù)賦值給一個(gè)變量(這里是f),f就是他的函數(shù)名,后面就可以直接調(diào)用啦~,但是這種簡單使用的情況實(shí)際上會(huì)不會(huì)用到呢?很殘酷,幾乎沒有。
匿名函數(shù)配合下面的場景使用效果更佳。
閉包
你有沒有一種情況,常常要定義好多全局變量來共享數(shù)據(jù),這種變量一旦多了非常難看,還會(huì)污染環(huán)境,有沒有一種辦法,可以通過重復(fù)調(diào)用同一個(gè)函數(shù),來修改函數(shù)內(nèi)部的變量呢?
我翻來覆去發(fā)現(xiàn)是真的有!這個(gè)東西就叫閉包!
閉包的簡單實(shí)現(xiàn),把函數(shù)定義在函數(shù)內(nèi)部,并當(dāng)作返回值返回。
func?closureSample()?func()?{?count?:=?0
?return?func()?{
??count?++
??fmt.Printf("調(diào)用次數(shù)?%v?\n",?count)
?}
}
怎么用才爽?我先喪心病狂的調(diào)用兩次closureSample函數(shù),得到兩個(gè)函數(shù)c1、c2,這兩個(gè)函數(shù)就是closureSample函數(shù)的返回值,類型是一個(gè)匿名函數(shù)。
c1,?c2?:=?closureSample(),?closureSample()瘋狂調(diào)用!!!
?c1()?c1()
?c1()
?//?你會(huì)發(fā)現(xiàn)c2又從1開始輸出,因?yàn)閮蓚€(gè)函數(shù)的變量是獨(dú)立使用的
?c2()
?c2()
輸出
調(diào)用次數(shù) 1調(diào)用次數(shù) 2
調(diào)用次數(shù) 3
調(diào)用次數(shù) 1
調(diào)用次數(shù) 2
調(diào)用次數(shù) 3
神奇不神奇!在調(diào)用c2的時(shí)候,完全沒有影響到c1!
這是因?yàn)楦鱾€(gè)函數(shù)是獨(dú)立使用一套自己的內(nèi)部變量,互相不影響,所以閉包也可以當(dāng)測試用例使用。
用來傳入不同的實(shí)現(xiàn),重復(fù)調(diào)用得到不同的返回,不用定義全局變量。
- 好處:可以減少全局變量防止變量污染
- 壞處:延長了局部變量和函數(shù)的生命周期,增加了 gc 的壓力
閉包形式 2
通過上面的例子,不難發(fā)現(xiàn)閉包內(nèi)部的匿名函數(shù)可以使用到外部的變量。
閉包形式 2,立即執(zhí)行函數(shù),聲明完以后加括號,用以表示即刻調(diào)用。
func()?{??//?to?do?something
?}()
閉包存在的 bug
go 里創(chuàng)建一個(gè)協(xié)程(類似于子線程)非常的容易,只要在語句前加一個(gè)go關(guān)鍵字就可以了。看看下面這個(gè)函數(shù)會(huì)出現(xiàn)什么問題。
for?i?:=?0;?i?3;?i++?{??fmt.Printf("第一次?i?產(chǎn)生變化中?%v?\n",?i)
??go?func()?{
???fmt.Printf("第一次輸出:?%v\n",?i)
??}()
?}
?time.Sleep(time.Second)
協(xié)程創(chuàng)建完以后立即會(huì)執(zhí)行,但是協(xié)程創(chuàng)建這個(gè)事件和協(xié)程執(zhí)行代碼是分離的,他可以全部創(chuàng)建完再執(zhí)行,而且主線程和協(xié)程是同時(shí)運(yùn)行的(并發(fā)),有可能主線程執(zhí)行完了,協(xié)程還沒執(zhí)行。
這個(gè)時(shí)候協(xié)程才會(huì)調(diào)用外部的變量,i 已經(jīng)變成 3 了。
第一次 i 產(chǎn)生變化中 0第一次 i 產(chǎn)生變化中 1
第一次 i 產(chǎn)生變化中 2
第一次輸出:3
第一次輸出:3
第一次輸出:3
解決辦法,創(chuàng)建副本,可以給匿名函數(shù)加一個(gè)參數(shù),傳值過來自動(dòng)生成副本
for?i?:=?0;?i?3;?i++?{??fmt.Printf("第二次?i?產(chǎn)生變化中?%v?\n",?i)
??go?func(tmp?int)?{
???fmt.Printf("第二次輸出:?%v\n",?tmp)
??}(i)
?}
time.Sleep(time.Second)
輸出
第二次 i 產(chǎn)生變化中 0第二次 i 產(chǎn)生變化中 1
第二次輸出:0
第二次 i 產(chǎn)生變化中 2
第二次輸出:2
第二次輸出:1
第二種創(chuàng)建副本的形式
for?i?:=?0;?i?3;?i++?{??fmt.Printf("第三次?i?產(chǎn)生變化中?%v?\n",?i)
??tmp?:=?i
??go?func()?{
???fmt.Printf("第三次輸出:?%v\n",?tmp)
??}()
?}
?time.Sleep(time.Second)
輸出
第三次?i?產(chǎn)生變化中?0第三次?i?產(chǎn)生變化中?1
第三次?i?產(chǎn)生變化中?2
第三次輸出:?0
第三次輸出:?2
第三次輸出:?1
推薦閱讀
Go語言函數(shù)深度解析(上)
喜歡本文的朋友,歡迎關(guān)注“Go語言中文網(wǎng)”:
Go語言中文網(wǎng)啟用微信學(xué)習(xí)交流群,歡迎加微信:274768166,投稿亦歡迎
如有收獲,點(diǎn)個(gè)在看,誠摯感謝
總結(jié)
以上是生活随笔為你收集整理的语言中拟合函数 计算aic_Go语言函数深度解析(中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生产环境可以用吗_小型熔喷布设备可以生产
- 下一篇: 汉语是什么_为什么出国留学以及工作要考国