記golang中結(jié)構(gòu)體切片轉(zhuǎn)指針踩坑

背景:

?? 開發(fā)階段發(fā)現(xiàn)某數(shù)據(jù)結(jié)構(gòu)切片中,字段值都相等揭措,經(jīng)排查后發(fā)現(xiàn)某次對結(jié)構(gòu)體實例切片進(jìn)行for循環(huán)遍歷胆数,以修改字段數(shù)值時,出現(xiàn)問題黎泣。

示例代碼:

# forTest 模擬遍歷循環(huán)結(jié)構(gòu)體過程
func forTest() {

    // 定義函數(shù)內(nèi)部結(jié)構(gòu)體
    type forStruct struct {
        ID   int
        Name string
    }

    // 生成數(shù)據(jù)切片恕刘,并進(jìn)行賦值操作
    list := make([]forStruct, 0)
    list = append(list, forStruct{1, "測試1"}, forStruct{2, "測試2"})
    // 存放遍歷后修改的結(jié)果,其中result是結(jié)構(gòu)體指針類型
    result := make([]*forStruct, 0)

    // 開始遍歷數(shù)據(jù)抒倚,并打印出相關(guān)結(jié)果
    for i, v := range list {
        // 修改前數(shù)據(jù)
        fmt.Println(fmt.Sprintf("第%d行數(shù)據(jù):%v", i, v))

        // 將ID值+10
        v.ID = v.ID + 10

        // 修改后數(shù)據(jù)
        fmt.Println(fmt.Sprintf("第%d行修改數(shù)據(jù):%v", i, v))

        // 臨時變量m的值
        fmt.Println(fmt.Sprintf("v臨時變量的地址:%v", &v))

        // 切片原變量的值
        fmt.Println(fmt.Sprintf("切片原變量的地址:%v", &list[i]))

        fmt.Println("------------------------------------------")

        result = append(result, &v)
    }

    // 遍歷返回的結(jié)果
    for i, r := range result {
        fmt.Println(fmt.Sprintf("第%d行數(shù)據(jù)為%v", i, r))
    }

}
輸出結(jié)果:
第0行數(shù)據(jù):{1 測試1}
第0行修改數(shù)據(jù):{11 測試1}
v臨時變量的地址:&{11 測試1}
切片原變量的地址:&{1 測試1}
------------------------------------------
第1行數(shù)據(jù):{2 測試2}
第1行修改數(shù)據(jù):{12 測試2}
v臨時變量的地址:&{12 測試2}
切片原變量的地址:&{2 測試2}
------------------------------------------
第0行數(shù)據(jù)為&{12 測試2}
第1行數(shù)據(jù)為&{12 測試2}

??可以看到輸出的最后兩行都是相同的褐着,這是什么原因呢?

原因

?? golang中的參數(shù)傳遞都是值傳遞!
??在for循環(huán)遍歷slice或者map時托呕,生成了臨時變量v献起,變量v在遍歷過程中,是重復(fù)利用的镣陕。也就是說谴餐,無論是第幾次遍歷,始終都是將slice或者map中的數(shù)據(jù)復(fù)制到了v中呆抑,并通過操作v來實現(xiàn)內(nèi)部變量岂嗓。
??在上述示例代碼中,處理邏輯是將遍歷結(jié)構(gòu)體數(shù)據(jù)切片并修改字段后鹊碍,存入到結(jié)構(gòu)體指針切片中厌殉,在此過程中食绿,變量v的內(nèi)存地址始終不變,存入的均為臨時變量的地址公罕。等循環(huán)結(jié)束后器紧,由于golang使用的是引用計數(shù)算法,因此v并不會被垃圾回收楼眷,存入的所有結(jié)構(gòu)體數(shù)據(jù)均為最后一次遍歷的數(shù)據(jù)铲汪。

解決方式:

  1. 原切片改用指針類型:數(shù)據(jù)相同是由于存入的是臨時變量地址,因此只需要將原本的切片存入類型從結(jié)構(gòu)體統(tǒng)一成結(jié)構(gòu)體指針即可罐柳。在操作v的時候掌腰,實際會操作切片底層的數(shù)據(jù),操作完成后再次存儲指針即可张吉,或者直接使用原本的切片齿梁。
  2. 結(jié)果切片改為結(jié)構(gòu)體: 與存入指針相對,也可以存為結(jié)構(gòu)體肮蛹。在遍歷過程中勺择,會生成一個新的結(jié)構(gòu)體對象,并將這個結(jié)構(gòu)實例存入結(jié)果中伦忠。不過建議大數(shù)據(jù)結(jié)構(gòu)體還是使用指針省核,以減少內(nèi)存復(fù)制成本。
  3. 直接操作原切片: 上述兩種方式都是原現(xiàn)的切片類型統(tǒng)一缓苛,如果仍需要結(jié)構(gòu)體轉(zhuǎn)換為指針類型芳撒,則可不操作臨時變量v,直接操作原變量未桥,并將原變量賦值到結(jié)果集笔刹。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冬耿,隨后出現(xiàn)的幾起案子舌菜,更是在濱河造成了極大的恐慌,老刑警劉巖亦镶,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件日月,死亡現(xiàn)場離奇詭異,居然都是意外死亡缤骨,警方通過查閱死者的電腦和手機(jī)爱咬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绊起,“玉大人精拟,你說我怎么就攤上這事。” “怎么了蜂绎?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵栅表,是天一觀的道長。 經(jīng)常有香客問我师枣,道長怪瓶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任践美,我火速辦了婚禮洗贰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拨脉。我一直安慰自己哆姻,他們只是感情好宣增,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布玫膀。 她就那樣靜靜地躺著,像睡著了一般爹脾。 火紅的嫁衣襯著肌膚如雪帖旨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天灵妨,我揣著相機(jī)與錄音解阅,去河邊找鬼。 笑死泌霍,一個胖子當(dāng)著我的面吹牛货抄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朱转,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蟹地,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了藤为?” 一聲冷哼從身側(cè)響起怪与,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缅疟,沒想到半個月后分别,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡存淫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年耘斩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桅咆。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡括授,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刽脖,我是刑警寧澤羞海,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站曲管,受9級特大地震影響却邓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜院水,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一腊徙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧檬某,春花似錦撬腾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至场斑,卻和暖如春漓踢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背漏隐。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工喧半, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人青责。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓挺据,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脖隶。 傳聞我的和親對象是個殘疾皇子扁耐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容