Go語言最新面試題及其解析

w1015357065發表於2019-12-30

點選連結,檢視剩餘 6 道面試題及其解析  


簡介: 最近在很多地方看到了 go 語言的面試題,看到了很多人對 Go 語言的面試題心存恐懼,也是為了複習基礎,我把解題的過程總結下來。


1、寫出下面程式碼輸出內容。

package mainimport ( "fmt") func main() { defer_call()}func defer_call() { defer func() { fmt.Println("列印前") }() defer func() { fmt.Println("列印中") }() defer func() { fmt.Println("列印後") }() panic("觸發異常")}

考點:defer 執行順序 解答: defer 是後進先出。 協程遇到 panic 時,遍歷本協程的 defer 連結串列,並執行 defer。在執行 defer 過程中,遇到 recover 則停止 panic,返回 recover 處繼續往下執行。如果沒有遇到 recover,遍歷完本協程的 defer 連結串列後,向 stderr 丟擲 panic 資訊。從執行順序上來看,實際上是按照先進後出的順序執行 defer

列印後
列印中
列印前
panic: 觸發異常
注意:請用獨立終端執行,排查某些 IDE 對 stderr 和 stdout 處理問題導致輸出順序不一致。

2、以下程式碼有什麼問題,說明原因。

type student struct { Name string Age int}func pase_student() { m := make(map[string]*student) stus := [] student{ {Name: "zhou", Age: 24}, {Name: "li", Age: 23}, {Name: "wang", Age: 22}, } for _, stu := range stus { m[stu.Name] = &stu }}

考點:foreach 解答: 這樣的寫法初學者經常會遇到的,很危險! 與 Java 的 foreach 一樣,都是使用副本的方式。所以 m[stu.Name]=&stu 實際上一致指向同一個指標, 最終該指標的值為遍歷的最後一個 struct 的值拷貝。 就像想修改切片元素的屬性:

for _, stu := range stus { stu.Age = stu.Age+10}
也是不可行的。 大家可以試試列印出來:

func pase_student() { m := make(map[string]*student) stus := [] student{ {Name: "zhou", Age: 24}, {Name: "li", Age: 23}, {Name: "wang", Age: 22}, } // 錯誤寫法 for _, stu := range stus { m[stu.Name] = &stu } for k,v:=range m{ println(k,"=>",v.Name) } // 正確 for i:=0;i<len(stus);i++ { m[stus[i].Name] = &stus[i] } for k,v:=range m{ println(k,"=>",v.Name) }}

3、下面的程式碼會輸出什麼,並說明原因

func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { fmt.Println("A: ", i) wg.Done() }() } for i := 0; i < 10; i++ { go func(i int) { fmt.Println("B: ", i) wg.Done() }(i) } wg.Wait()}

考點:go 執行的隨機性和閉包 解答: 誰也不知道執行後列印的順序是什麼樣的,所以只能說是隨機數字。
其中 A:輸出完全隨機,取決於 goroutine 執行時 i 的值是多少;
而 B:一定輸出為 0~9,但順序不定。

第一個 go func 中 i 是外部 for 的一個變數,地址不變化,但是值都在改變。

第二個 go func 中 i 是函式引數,與外部 for 中的 i 完全是兩個變數。
尾部 (i) 將發生值拷貝,go func 內部指向值拷貝地址。

所以在使用 goroutine 在處理閉包的時候,避免發生類似第一個 go func 中的問題。

4、下面程式碼會輸出什麼?

type People struct{}func (p *People) ShowA() { fmt.Println("showA") p.ShowB()}func (p *People) ShowB() { fmt.Println("showB")}type Teacher struct { People}func (t *Teacher) ShowB() { fmt.Println("teacher showB")}func main() { t := Teacher{} t.ShowA()}
考點:go 的組合繼承 解答: 這是 Golang 的組合模式,可以實現 OOP 的繼承。 被組合的型別 People 所包含的方法雖然升級成了外部型別 Teacher 這個組合型別的方法(一定要是匿名欄位),但它們的方法 (ShowA()) 呼叫時接受者並沒有發生變化。 此時 People 型別並不知道自己會被什麼型別組合,當然也就無法呼叫方法時去使用未知的組合者 Teacher 型別的功能。

showAshowB
5、下面程式碼會觸發異常嗎?請詳細說明

func main() { runtime.GOMAXPROCS(1) int_chan := make(chan int, 1) string_chan := make(chan string, 1) int_chan <- 1 string_chan <- "hello" select { case value := <-int_chan: fmt.Println(value) case value := <-string_chan: panic(value) }}
考點:select 隨機性 解答: select 會隨機選擇一個可用通用做收發操作。 所以程式碼是有肯觸發異常,也有可能不會。 單個 chan 如果無緩衝時,將會阻塞。但結合 select 可以在多個 chan 間等待執行。有三點原則: select 中只要有一個 case 能 return,則立刻執行。 當如果同一時間有多個 case 均能 return 則偽隨機方式抽取任意一個執行。 * 如果沒有一個 case 能 return 則可以執行” default” 塊。

關鍵字:go 語言 面試


更多原創文章乾貨分享,請關注公眾號
  • Go語言最新面試題及其解析
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章