深入理解Go語言中指針接收器與值接收器的區別

超級歐派課程 2024-03-30 03:10:43

這篇文章將探討關于Go語言中指針接收器和值接收器之間的細微差別。我們將逐步介紹這些差別,並通過示例代碼進行說明。

1. 什麽是值接收器與指針接收器?

Go語言中,每個方法都與一個接收器綁定,接收器可以是值類型(值接收器)或者是指向值類型的指針(指針接收器)。

值接收器:它基于值類型的副本來調用方法;任何對接收器的修改都不會影響原始值。指針接收器:它使用原始值的指針來調用方法;對接收器的修改將反映在原始值上。

2. 值類型和指針類型的方法調用

首先,無論是值類型T還是指針類型*T(前提是可尋址),它們都可以調用具有值接收器和指針接收器的方法。這是最基本的原則。

例如,如果一個類型有一個值接收器的方法,那麽它可以在該類型的值本身和指向該值的指針上進行調用。同樣地,對于指針接收器的方法,它可以在指針和該指針所指向的值本身上進行調用。

示例代碼如下:

上述示例代碼可以正常運行,沒有任何編譯錯誤。

需要注意的是,即使變量m不是指針類型,調用m.Transform()​仍然會改變其Model​值。這是因爲Go語言會自動取值的地址來調用指針接收器方法,所以這相當于使用(&m).Transform()​的另一種方式。

所以,我們可以得出兩個要點:

Go語言會自動取值的地址來調用指針接收器方法。它會自動解引用指針來調用值接收器方法。

這個細節經常被人們誤解,實際上我們可以只使用值來調用指針接收器方法,而不需要使用指針。

3. nil的細微差別

接下來,我們來討論一下關于nil指針的細微差別。讓我們稍微修改一下例子,看看哪個例子會因爲nil而導致恐慌。

這兩個例子都不會引發恐慌,實際上我們可以使用nil指針調用函數,前提是該方法不訪問結構體的任何字段。

但是,我們之前討論過"Go在調用值接收器方法時會自動解引用指針"。那麽,如果我們使用nil指針調用值接收器方法會發生什麽呢?會導致恐慌嗎?

是的,嘗試在nil指針上調用值接收器方法(例如var car *Car; car.Move()​)會導致恐慌,因爲Go無法在運行時將nil解引用並將其作爲值傳遞。

4. 不可尋址的問題

接下來,我們來解決第一個要點的問題:"Go會自動取值的地址來調用指針接收器"。如果該值是"不可尋址"的,會發生什麽呢?

從函數返回的值或臨時值(例如結構體字面量或映射中的值)通常無法被尋址,因此無法在其上調用指針接收器方法。

下面是一個示例:

在這個示例中,我們試圖在一個結構體字面量上調用指針接收器方法SetName​,但是它會導致編譯錯誤。這是因爲結構體字面量是不可尋址的,無法獲取其指針。

要解決這個問題,我們可以首先將結構體字面量分配給一個變量,然後使用該變量調用方法:

這樣就可以成功調用指針接收器方法了。

總結:無論是值類型還是指針類型,都可以調用具有值接收器和指針接收器的方法。使用指針調用值接收器方法會自動解引用指針。使用nil指針調用指針接收器方法是安全的,前提是該方法不訪問結構體的任何字段。無法在不可尋址的值上調用指針接收器方法,需要先將其分配給一個變量。更多

希望這些解釋能夠幫助你更好地理解Go語言中指針接收器和值接收器之間的細微差別。如果你想了解更多的 golang 知識,請關注我的《Golang實用技巧》專欄,它將爲你揭秘生産環境最佳實踐,帶你探索高並發編程的實用教程。從分享實用的Golang小技巧到深入剖析實際應用場景,讓你成爲真正的Golang大師。無論你是初學者還是經驗豐富的開發者,這裏都有你所需要的靈感和知識。讓我們一同探索Golang的無限可能!

0 阅读:0

超級歐派課程

簡介:感謝大家的關注