Go開發(fā)工程師
未來3-5年企業(yè)高性能項(xiàng)目不可替代的語言,從基礎(chǔ)到項(xiàng)目實(shí)戰(zhàn)再到重構(gòu),真正從入門到精通
我們?cè)谇懊娑啻翁岬竭^指針及指針類型。例如,*Person
是Person
的指針類型。又例如,表達(dá)式&p
的求值結(jié)果是p
的指針。方法的接收者類型的不同會(huì)給方法的功能帶來什么影響?該方法所屬的類型又會(huì)因此發(fā)生哪些潛移默化的改變?現(xiàn)在,我們就來解答第一個(gè)問題。至于第二個(gè)問題,我會(huì)在下一小節(jié)予以解答。
指針操作涉及到兩個(gè)操作符——&
和*
。這兩個(gè)操作符均有多個(gè)用途。但是當(dāng)它們作為地址操作符出現(xiàn)時(shí),前者的作用是取址,而后者的作用是取值。更通俗地講,當(dāng)?shù)刂凡僮鞣?code class="marker">&被應(yīng)用到一個(gè)值上時(shí)會(huì)取出指向該值的指針值,而當(dāng)?shù)刂凡僮鞣?code class="marker">*被應(yīng)用到一個(gè)指針值上時(shí)會(huì)取出該指針指向的那個(gè)值。它們可以被視為相反的操作。
除此之外,當(dāng)*
出現(xiàn)在一個(gè)類型之前(如*Person
和*[3]string
)時(shí)就不能被看做是操作符了,而應(yīng)該被視為一個(gè)符號(hào)。如此組合而成的標(biāo)識(shí)符所表達(dá)的含義是作為第二部分的那個(gè)類型的指針類型。我們也可以把其中的第二部分所代表的類型稱為基底類型。例如,*[3]string
是數(shù)組類型[3]string
的指針類型,而[3]string
是*[3]string
的基底類型。
好了,我們現(xiàn)在回過頭去再看結(jié)構(gòu)體類型Person
。它及其兩個(gè)方法的完整聲明如下:
type Person struct { Name string Gender string Age uint8 Address string } func (person *Person) Grow() { person.Age++ } func (person *Person) Move(newAddress string) string { old := person.Address person.Address = newAddress return old }
注意,Person
的兩個(gè)方法Grow
和Move
的接收者類型都是*Person
,而不是Person
。只要一個(gè)方法的接收者類型是其所屬類型的指針類型而不是該類型本身,那么我就可以稱該方法為一個(gè)指針方法。上面的Grow
方法和Move
方法都是Person
類型的指針方法。
相對(duì)的,如果一個(gè)方法的接收者類型就是其所屬的類型本身,那么我們就可以把它叫做值方法。我們只要微調(diào)一下Grow
方法的接收者類型就可以把它從指針方法變?yōu)橹捣椒ǎ?/p>
func (person Person) Grow() { person.Age++ }
那指針方法和值方法到底有什么區(qū)別呢?我們?cè)诒A羯鲜鲂薷牡那疤嵯戮帉懭缦麓a:
p := Person{"Robert", "Male", 33, "Beijing"} p.Grow() fmt.Printf("%v\n", p)
這段代碼被執(zhí)行后,標(biāo)準(zhǔn)輸出會(huì)打印出什么內(nèi)容呢?直覺上,34
會(huì)被打印出來,但是被打印出來的卻是33
。這是怎么回事呢?Grow
方法的功能失效了?!
解答這個(gè)問題需要引出一條定論:方法的接收者標(biāo)識(shí)符所代表的是該方法當(dāng)前所屬的那個(gè)值的一個(gè)副本,而不是該值本身。例如,在上述代碼中,Person
類型的Grow
方法的接收者標(biāo)識(shí)符person
代表的是p
的值的一個(gè)拷貝,而不是p
的值。我們?cè)谡{(diào)用Grow
方法的時(shí)候,Go語言會(huì)將p
的值復(fù)制一份并將其作為此次調(diào)用的當(dāng)前值。正因?yàn)槿绱耍?code class="marker">Grow方法中的person.Age++
語句的執(zhí)行會(huì)使這個(gè)副本的Age
字段的值變?yōu)?code class="marker">34,而p
的Age
字段的值卻依然是33
。這就是問題所在。
只要我們把Grow
變回指針方法就可以解決這個(gè)問題。原因是,這時(shí)的person
代表的是p
的值的指針的副本。指針的副本仍會(huì)指向p
的值。另外,之所以選擇表達(dá)式person.Age
成立,是因?yàn)槿绻鸊o語言發(fā)現(xiàn)person
是指針并且指向的那個(gè)值有Age
字段,那么就會(huì)把該表達(dá)式視為(*person).Age
。其實(shí),這時(shí)的person.Age
正是(*person).Age
的速記法。
在命令源碼文件index.go中,我已經(jīng)編寫好了結(jié)構(gòu)體類型MyInt
及其兩個(gè)方法。我希望在該文件被運(yùn)行之后在標(biāo)準(zhǔn)輸出上打印出true
。但是好像哪里出了問題,致使標(biāo)準(zhǔn)輸出上總是出現(xiàn)false
。你能幫我找出問題所在并修正它嗎?要求僅對(duì)一處做出修改。
把MyInt
類型的Decrease
方法由值方法改為指針方法即可。至于怎樣改請(qǐng)回顧本節(jié)的“知識(shí)要點(diǎn)”。
請(qǐng)驗(yàn)證,完成請(qǐng)求
由于請(qǐng)求次數(shù)過多,請(qǐng)先驗(yàn)證,完成再次請(qǐng)求
打開微信掃碼自動(dòng)綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)