踩坑 - Golang 指針數(shù)值

?? 目錄

  • ?? 背景
  • ?? Demo
    • ? 坑點一:修改變量值導致通過地址引用該變量的地方也發(fā)生了修改
    • ? 坑點二:直接修改內存值的操作比較危險
  • ?? 總結與經驗

?? 背景

前幾天發(fā)現(xiàn)了一個 bug慷荔,查了半天發(fā)現(xiàn)是一個指針類型賦值的問題,這里做一個 demo 演示一下,以后盡量規(guī)避下

?? Demo

當時遇到的問題可以用下面這個場景概括下

王家兩個兄弟褥紫,一個是王明玄货,一個是王平
王明的英文名字是 ming wang
復制了王明創(chuàng)建了王平材彪,并且修改王平的 FirstName 為 ping

期望王明的英文名字是 ming wang酱畅,王平的名字是 ping wang

但是結果他們的名字都是 ping wang弄喘,這不符合預期

package main

import "fmt"

type Name struct {
    LastName  string
    FirstName *string
}

func (n Name) String() string {
    return fmt.Sprintf("%s %s", *n.FirstName, n.LastName)
}

func main() {

    first := "ming"
    last := "wang"
    wangming := Name{
        LastName:  last,
        FirstName: &first,
    }

    wangping := wangming

    first = "ping"
    *wangping.FirstName = first

    fmt.Println("wangming name is", wangming)
    fmt.Println("wangping name is", wangping)
}
---
wangming name is ping wang
wangping name is ping wang

短短的代碼则拷,其實有兩個問題贡蓖,我們依次分析下

? 坑點一:修改變量值導致通過地址引用該變量的地方也發(fā)生了修改

讓我們斷點來看下,看下王明和王平是怎么了煌茬,怎么搞到一起了

first 修改導致的問題

可以看到斥铺,在 first = "ping" 將 first 的值修改成了 ping 時,此刻就影響了王明的 FirstName坛善,因為王明的 FirstName 對應內存地址的就是 first 的內存地址

如果 first 發(fā)生了變化晾蜘,王明的 FirstName 也就跟隨發(fā)生了變化,從 ming wang 變成了 ping wang

既然上面是引用共用的 first 變量導致的問題眠屎,那我們新創(chuàng)建一個變量剔交,不再使用 first 變量,應該可以解決這個問題

package main

import "fmt"

type Name struct {
    LastName  string
    FirstName *string
}

func (n Name) String() string {
    return fmt.Sprintf("%s %s", *n.FirstName, n.LastName)
}

func main() {
    first := "ming"
    last := "wang"
    wangming := Name{
        LastName:  last,
        FirstName: &first,
    }

    wangping := wangming
    ping := "ping"
    *wangping.FirstName = ping

    fmt.Println("wangming name is", wangming)
    fmt.Println("wangping name is", wangping)
}
---
wangming name is ping wang
wangping name is ping wang

很可惜改衩,貌似并沒有生效

? 坑點二:直接修改內存值的操作比較危險

我們再打斷點看下問題出現(xiàn)在哪里

相同的內存地址

王平的 FirstName 和王明的 FirstName 內存地址竟然是一樣的岖常,不是明明使用了新的變量了嗎

原因是 *wangping.FirstName = ping 這個操作,直接操作了內存值葫督,修改了 FirstName 這個內存地址對應的值

wangming 的 FirstName 和 wangping 的 FirstName 的內存地址是一個竭鞍,所以 *wangping.FirstName = ping 這個操作,就影響了這兩位的 FirstName 了

那我們不修改內存地址的值候衍,直接換個新內存地址的值嘞

package main

import "fmt"

type Name struct {
    LastName  string
    FirstName *string
}

func (n Name) String() string {
    return fmt.Sprintf("%s %s", *n.FirstName, n.LastName)
}

func main() {
    first := "ming"
    last := "wang"
    wangming := Name{
        LastName:  last,
        FirstName: &first,
    }

    wangping := wangming
    ping := "ping"
    wangping.FirstName = &ping

    fmt.Println("wangming name is", wangming)
    fmt.Println("wangping name is", wangping)
}

踩了兩個坑之后笼蛛,這次好使了

這次好使了

?? 總結與經驗

這是之前是在處理一個 k8s 的資源時遇到的問題,因為資源默認提供了 deepCopy 的方式蛉鹿,因此通過 deepCopy 的方式繞了過去解決了問題滨砍,這里不展開講

后來在考慮往之前的版本 cherry-pick 這個修改的時候,通過單元測試發(fā)現(xiàn),之前版本的代碼沒有這樣的問題惋戏,所以才想起來這個問題除了 deepCopy 還有其他解決辦法

總結來說领追,為了后面少處理類似的 bug,需要注意以下兩點

  1. 結構體中盡量少的使用基本類型的指針值
  2. 處理這種基本類型指針值的時候响逢,額外留意一下绒窑,盡量避免通過 *xx=xx 直接修改變量的值
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舔亭,隨后出現(xiàn)的幾起案子些膨,更是在濱河造成了極大的恐慌,老刑警劉巖钦铺,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件订雾,死亡現(xiàn)場離奇詭異,居然都是意外死亡矛洞,警方通過查閱死者的電腦和手機洼哎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沼本,“玉大人噩峦,你說我怎么就攤上這事〕檎祝” “怎么了识补?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辫红。 經常有香客問我李请,道長,這世上最難降的妖魔是什么厉熟? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮较幌,結果婚禮上揍瑟,老公的妹妹穿的比我還像新娘。我一直安慰自己乍炉,他們只是感情好绢片,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岛琼,像睡著了一般底循。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上槐瑞,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天熙涤,我揣著相機與錄音,去河邊找鬼。 笑死祠挫,一個胖子當著我的面吹牛那槽,可吹牛的內容都是我干的。 我是一名探鬼主播等舔,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼骚灸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了慌植?” 一聲冷哼從身側響起甚牲,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝶柿,沒想到半個月后丈钙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡只锭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年著恩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜻展。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡喉誊,死狀恐怖,靈堂內的尸體忽然破棺而出纵顾,到底是詐尸還是另有隱情伍茄,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布施逾,位于F島的核電站敷矫,受9級特大地震影響,放射性物質發(fā)生泄漏汉额。R本人自食惡果不足惜曹仗,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蠕搜。 院中可真熱鬧怎茫,春花似錦、人聲如沸妓灌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虫埂。三九已至祥山,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掉伏,已是汗流浹背缝呕。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工澳窑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岳颇。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓照捡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親话侧。 傳聞我的和親對象是個殘疾皇子栗精,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容