Go語言面試題:為什么for range循環(huán)中使用指針會導(dǎo)致所有值變成最后一個元素?

Go語言面試題:為什么for range循環(huán)中使用指針會導(dǎo)致所有值變成最后一個元素?

go語言面試題:深入理解for…range循環(huán)指針

Go語言的for…range循環(huán)簡潔高效,但使用指針時容易引發(fā)誤解。本文剖析一個常見的面試題,闡明for…range循環(huán)中指針的陷阱及解決方法

問題描述

考慮一個學(xué)生結(jié)構(gòu)體和學(xué)生切片,目標(biāo)是將學(xué)生信息存儲到map中并打印姓名:

type student struct {     name string     age  int }  func main() {     m := make(map[string]*student)     stus := []student{         {name: "pprof.cn", age: 18},         {name: "測試", age: 23},         {name: "博客", age: 28},     }      for _, stu := range stus {         m[stu.name] = &stu     }     for k, v := range m {         fmt.Println(k, "=>", v.name)     } }

預(yù)期輸出:

pprof.cn => pprof.cn 測試 => 測試 博客 => 博客

實際輸出:

立即學(xué)習(xí)go語言免費學(xué)習(xí)筆記(深入)”;

pprof.cn => 博客 測試 => 博客 博客 => 博客

問題分析

所有v.name都變成了”博客”,原因在于for…range循環(huán)的迭代變量stu在每次迭代中是同一個變量,只是其值被更新。&stu創(chuàng)建的指針始終指向這個單一變量。循環(huán)結(jié)束后,stu的值為最后一個學(xué)生的信息,因此map中的所有指針都指向了這個最終的stu變量。

Go語言的for…range循環(huán)復(fù)用迭代變量,不會為每次迭代創(chuàng)建新變量。因此,獲取迭代變量的地址將始終得到同一個地址。

解題方法

為了解決這個問題,需要在每次迭代中創(chuàng)建stu的副本:

for _, stu := range stus {     stuCopy := stu // 創(chuàng)建副本     m[stu.name] = &stuCopy }

通過創(chuàng)建stuCopy副本,并使用&stuCopy作為map的值,確保每個學(xué)生的信息都被獨立存儲和引用。

正確輸出

修改后的代碼將產(chǎn)生預(yù)期的輸出:

pprof.cn => pprof.cn 測試 => 測試 博客 => 博客

總結(jié)

本例揭示了for…range循環(huán)中使用指針的潛在風(fēng)險。 理解迭代變量的復(fù)用機制,并在必要時創(chuàng)建副本,是避免此類問題的關(guān)鍵。 這對于Go語言開發(fā)者來說是一個重要的知識點。

以上就是Go語言面試題:

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊10 分享