簡介:?本文即Go語言的那些坑三擅编。
本文即Go語言的那些坑三蜕猫。
不要對Go并發(fā)函數(shù)的執(zhí)行時機做任何假設
請看下列的列子:
1import(2"fmt"3"runtime"4"time"5)6func main(){7names := []string{"lily","yoyo","cersei","rose","annei"}8for_,name:= range names{9go func(){10fmt.Println(name)11}()12}13runtime.GOMAXPROCS(1)14runtime.Gosched()15}
請問輸出什么?
答案:
1annei2annei3annei4annei5annei
為什么呢腹备?是不是有點詫異衬潦?
輸出的都是“annei”,而“annei”又是“names”的最后一個元素植酥,那么也就是說程序打印出了最后一個元素的值别渔,而name對于匿名函數(shù)來講又是一個外部的值。因此惧互,我們可以做一個推斷:雖然每次循環(huán)都啟用了一個協(xié)程,但是這些協(xié)程都是引用了外部的變量喇伯,當協(xié)程創(chuàng)建完畢喊儡,再執(zhí)行打印動作的時候,name的值已經(jīng)不知道變?yōu)樯读说揪荩驗橹骱瘮?shù)協(xié)程也在跑艾猜,大家并行买喧,但是在此由于names數(shù)組長度太小,當協(xié)程創(chuàng)建完畢后匆赃,主函數(shù)循環(huán)早已結束淤毛,所以,打印出來的都是遍歷的names最后的那一個元素“annei”算柳。
如何證實以上的推斷呢低淡?
其實很簡單,每次循環(huán)結束后瞬项,停頓一段時間蔗蹋,等待協(xié)程打印當前的name便可。
1import(2"fmt"3"runtime"4"time"5)6func main(){7names := []string{"lily","yoyo","cersei","rose","annei"}8for_,name:= range names{9go func(){10fmt.Println(name)11}()12time.Sleep(time.Second)13}14runtime.GOMAXPROCS(1)15runtime.Gosched()16}
打印結果:
1lily2yoyo3cersei4rose5annei
以上我們得出一個結論囱淋,不要對“go函數(shù)”的執(zhí)行時機做任何的假設猪杭,除非你確實能做出讓這種假設成為絕對事實的保證。
假設T類型的方法上接收器既有T類型的妥衣,又有T指針類型的皂吮,那么就不可以在不能尋址的T值上調(diào)用T接收器的方法
請看代碼,試問能正常編譯通過嗎?
1import(2"fmt"3)4type Lili struct{5Name string6}7func (Lili *Lili) fmtPointer(){8fmt.Println("poniter")9}10func (Lili Lili) fmtReference(){11fmt.Println("reference")12}13func main(){14li := Lili{}15li.fmtPointer()16}
答案:
點擊鏈接税手,查看剩余內(nèi)容
https://developer.aliyun.com/article/619547?utm_content=g_1000095782
關鍵字:Go語言? ?題? ?答案