go語言錯題及答案整理

有隻黑白貓發表於2020-01-04

點選這裡,檢視剩餘錯題及答案

簡介: 本文即Go語言的那些坑三

不要對Go併發函式的執行時機做任何假設

請看下列的列子:

1import ( 2 "fmt" 3 "runtime" 4 "time" 5) 6func main(){ 7 names := []string{"lily", "yoyo", "cersei", "rose", "annei"} 8 for _, name := range names{ 9 go func(){10 fmt.Println(name)11 }()12 }13 runtime.GOMAXPROCS(1)14 runtime.Gosched()15}


請問輸出什麼?
答案:


1annei2annei3annei4annei5annei



為什麼呢?是不是有點詫異?
輸出的都是“annei”,而“annei”又是“names”的最後一個元素,那麼也就是說程式列印出了最後一個元素的值,而name對於匿名函式來講又是一個外部的值。因此,我們可以做一個推斷:雖然每次迴圈都啟用了一個協程,但是這些協程都是引用了外部的變數,當協程建立完畢,再執行列印動作的時候,name的值已經不知道變為啥了,因為主函式協程也在跑,大家並行,但是在此由於names陣列長度太小,當協程建立完畢後,主函式迴圈早已結束,所以,列印出來的都是遍歷的names最後的那一個元素“annei”。
如何證實以上的推斷呢?
其實很簡單,每次迴圈結束後,停頓一段時間,等待協程列印當前的name便可。


1import (2 "fmt"3 "runtime"4 "time"5)6func main(){7 names := []string{"lily", "yoyo", "cersei", "rose", "annei"}8 for _, name := range names{9 go func(){10 fmt.Println(name)11 }()12 time.Sleep(time.Second)13 }14 runtime.GOMAXPROCS(1)15 runtime.Gosched()16}


列印結果:

1lily2yoyo3cersei4rose5annei

以上我們得出一個結論,不要對“go函式”的執行時機做任何的假設,除非你確實能做出讓這種假設成為絕對事實的保證。
**假設T型別的方法上接收器既有T型別的,又有_T指標型別的,那麼就不可以在不能定址的T值上呼叫_T接收器的方法**

請看程式碼,試問能正常編譯通過嗎?


1import ( 2 "fmt" 3) 4type Lili struct{ 5 Name string 6} 7func (Lili *Lili) fmtPointer(){ 8 fmt.Println("poniter") 9}10func (Lili Lili) fmtReference(){11 fmt.Println("reference")12}13func main(){14 li := Lili{}15 li.fmtPointer()16}


答案:

關鍵字 Go語言 程式設計師 開發者

相關文章