最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang中接收者方法語法糖的使用方法詳解

 更新時間:2023年05月17日 08:34:31   作者:人艱不拆_zmc  
這篇文章主要為大家詳細(xì)介紹了Golang中接收者方法語法糖的使用方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的可以了解一下

1、概述

在《Golang常用語法糖》這篇博文中我們講解Golang中常用的12種語法糖,在本文我們主要講解下接收者方法語法糖。

在介紹Golang接收者方法語法糖前,先簡單說下Go 語言的指針 (Pointer),大致上理解如下:

  • 變量名前的 & 符號,是取變量的內(nèi)存地址,不是取值;
  • 數(shù)據(jù)類型前的 * 符號,代表要儲存的是對應(yīng)數(shù)據(jù)類型的內(nèi)存地址,不是存值;
  • 變量名前的 * 符號,代表從內(nèi)存地址中取值 (Dereferencing)。

注意 1:golang 指針詳細(xì)介紹請參見《Golang指針隱式間接引用》此篇博文。

2、接收者方法語法糖

在 Go 中,對于自定義類型 T,為它定義方法時,其接收者可以是類型 T 本身,也可能是 T 類型的指針 *T。

type Instance struct{}
 
func (ins *Instance) Foo() string {
 return ""
}

在上例中,我們定義了 Instance 的 Foo 方法時,其接收者是一個指針類型(*Instance)。

func main() {
 var _ = Instance{}.Foo() //編譯錯誤:cannot call pointer method on Instance{} ,變量是不可變的(該變量沒有地址,不能對其進(jìn)行尋址操作)
}

因此,如果我們用 Instance 類型本身 Instance{} 值去調(diào)用 Foo 方法,將會得到以上錯誤。

type Instance struct{}
 
func (ins Instance) Foo() string {
 return ""
}
 
func main() {
 var _ = Instance{}.Foo() // 編譯通過
}

此時,如果我們將 Foo 方法的接收者改為 Instance 類型,就沒有問題。

這說明,定義類型 T 的函數(shù)方法時,其接收者類型決定了之后什么樣的類型對象能去調(diào)用該函數(shù)方法。但,實際上真的是這樣嗎?

type Instance struct{}
 
func (ins *Instance) String() string {
 return ""
}
 
func main() {
 var ins Instance
 _ = ins.String() // 編譯器會自動獲取 ins 的地址并將其轉(zhuǎn)換為指向 Instance 類型的指針_ = (&ins).String()
}

實際上,即使是我們在實現(xiàn) Foo 方法時的接收者是指針類型,上面 ins 調(diào)用的使用依然沒有問題。

Ins 值屬于 Instance 類型,而非 *Instance,卻能調(diào)用 Foo 方法,這是為什么呢?這其實就是 Go 編譯器提供的語法糖!

當(dāng)一個變量可變時(也就是說,該變量是一個具有地址的變量,我們可以對其進(jìn)行尋址操作),我們對類型 T 的變量直接調(diào)用 *T 方法是合法的,因為 Go 編譯器隱式地獲取了它的地址。變量可變意味著變量可尋址,因此,上文提到的 Instance{}.Foo() 會得到編譯錯誤,就在于 Instance{} 值不能尋址。

注意 1:在 Go 中,即使變量沒有被顯式初始化,編譯器仍會為其分配內(nèi)存空間,因此變量仍然具有內(nèi)存地址。不過,由于變量沒有被初始化,它們在分配后僅被賦予其類型的默認(rèn)零值,而不是初始值。當(dāng)然,這些默認(rèn)值也是存儲在變量分配的內(nèi)存空間中的。

例如,下面的代碼定義了一個整型變量 x,它沒有被顯式初始化,但是在分配內(nèi)存時仍然具有一個地址:

var x int
fmt.Printf("%p\n", &x) // 輸出變量 x 的內(nèi)存地址

輸出結(jié)果類似于:0xc0000120a0,表明變量 x 的內(nèi)存地址已經(jīng)被分配了。但是由于變量沒有被初始化,x 的值將為整型的默認(rèn)值 0。  

3、深入測試

3.1 示例

package main
 
type B struct {
    Id int
}
 
func New() B {
    return B{}
}
 
func New2() *B {
    return &B{}
}
 
func (b *B) Hello() {
    return
}
 
func (b B) World() {
    return
}
 
func main() {
    // 方法的接收器為 *T 類型
    New().Hello() // 編譯不通過
 
    b1 := New()
    b1.Hello() // 編譯通過
 
    b2 := B{}
    b2.Hello() // 編譯通過
 
    (B{}).Hello() // 編譯不通過
    B{}.Hello()   // 編譯不通過
 
    New2().Hello() // 編譯通過
 
    b3 := New2()
    b3.Hello() // 編譯通過
 
    b4 := &B{} // 編譯通過
    b4.Hello() // 編譯通過
 
    (&B{}).Hello() // 編譯通過
 
    // 方法的接收器為 T 類型
    New().World() // 編譯通過
 
    b5 := New()
    b5.World() // 編譯通過
 
    b6 := B{}
    b6.World() // 編譯通過
 
    (B{}).World() // 編譯通過
    B{}.World()   // 編譯通過
 
    New2().World() // 編譯通過
 
    b7 := New2()
    b7.World() // 編譯通過
 
    b8 := &B{} // 編譯通過
    b8.World() // 編譯通過
 
    (&B{}).World() // 編譯通過
}

輸出結(jié)果:

./main.go:25:10: cannot call pointer method on New()
./main.go:25:10: cannot take the address of New()
./main.go:33:10: cannot call pointer method on B literal
./main.go:33:10: cannot take the address of B literal
./main.go:34:8: cannot call pointer method on B literal
./main.go:34:8: cannot take the address of B literal

3.2 問題總結(jié)

假設(shè) T 類型的方法上接收器既有 T 類型的,又有 *T 指針類型的,那么就不可以在不能尋址的 T 值上調(diào)用 *T 接收器的方法

  • &B{} 是指針,可尋址
  • B{} 是值,不可尋址
  • b := B{} b是變量,可尋址

4、總結(jié) 

在 Golang 中,當(dāng)一個變量是可變的(也就是說,該變量是一個具有地址的變量,我們可以對其進(jìn)行尋址操作),我們可以通過對該變量的指針進(jìn)行方法調(diào)用來執(zhí)行對該變量的操作,否則就會導(dǎo)致編譯錯誤。

到此這篇關(guān)于Golang中接收者方法語法糖的使用方法詳解的文章就介紹到這了,更多相關(guān)Golang語法糖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你搞懂Golang如何正確退出Goroutine

    一文帶你搞懂Golang如何正確退出Goroutine

    在Go語言中,Goroutine是一種輕量級線程,它的退出機(jī)制對于并發(fā)編程至關(guān)重要,下午就來介紹幾種Goroutine的退出機(jī)制,希望對大家有所幫助
    2023-06-06
  • Go語言中DateTime的用法介紹

    Go語言中DateTime的用法介紹

    這篇文章介紹了Go語言中DateTime的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • Golang最大遞減數(shù)算法問題分析

    Golang最大遞減數(shù)算法問題分析

    這篇文章主要介紹了Golang最大遞減數(shù)算法問題分析,結(jié)合實例形式分析了Go語言數(shù)字遍歷與運算相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • 淺析Go中關(guān)于零值和空值判斷的問題

    淺析Go中關(guān)于零值和空值判斷的問題

    這篇文章主要是對零值和空值判斷現(xiàn)狀進(jìn)行簡單的梳理和分享,文中的示例代碼講解詳細(xì),對我們深入了解go語言有一定的幫助,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-08-08
  • Go語言對字符串進(jìn)行MD5加密的方法

    Go語言對字符串進(jìn)行MD5加密的方法

    這篇文章主要介紹了Go語言對字符串進(jìn)行MD5加密的方法,實例分析了Go語言對字符串進(jìn)行md5加密的技巧,需要的朋友可以參考下
    2015-03-03
  • go語言接口之接口值舉例詳解

    go語言接口之接口值舉例詳解

    接口是一種抽象類型,是對其他類型行為的概括與抽象,從語法角度來看,接口是一組方法定義的集合,下面這篇文章主要給大家介紹了關(guān)于go語言接口之接口值的相關(guān)資料,文章通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • 深度解密 Go 語言中的 sync.map

    深度解密 Go 語言中的 sync.map

    這篇文章主要介紹了深度解密 Go 語言中的 sync.map,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Go語言中的定時器原理與實戰(zhàn)應(yīng)用

    Go語言中的定時器原理與實戰(zhàn)應(yīng)用

    在Go語言中,Timer和Ticker是處理定時任務(wù)的重要工具,Timer用于一次性事件,而Ticker則用于周期性事件,本文詳細(xì)介紹了這兩種定時器的創(chuàng)建、使用和停止方法,并通過實際案例展示了它們在監(jiān)控日志、檢查系統(tǒng)狀態(tài)等方面的應(yīng)用
    2024-10-10
  • Go語言標(biāo)準(zhǔn)庫flag的具體實現(xiàn)

    Go語言標(biāo)準(zhǔn)庫flag的具體實現(xiàn)

    Go語言的flag庫提供了一套簡單而強(qiáng)大的接口,用于解析命令行參數(shù),本文主要介紹了Go語言標(biāo)準(zhǔn)庫flag的具體實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • golang包的引入機(jī)制詳解

    golang包的引入機(jī)制詳解

    本文深入探討了Go語言中如何創(chuàng)建、組織和管理代碼包,以及包引入的多種使用場景和最佳實踐,通過閱讀本文,希望能幫助大家獲得全面而深入的理解,進(jìn)一步提升Go開發(fā)的效率和質(zhì)量
    2023-09-09

最新評論

庆阳市| 泾阳县| 普兰县| 南宁市| 陵水| 孝感市| 黄石市| 河南省| 南陵县| 砀山县| 东安县| 徐汇区| 稷山县| 安顺市| 淅川县| 大新县| 鄂伦春自治旗| 吴江市| 丹江口市| 营口市| 双江| 珲春市| 建阳市| 扶绥县| 遂昌县| 茌平县| 婺源县| 房山区| 三都| 驻马店市| 句容市| 安化县| 娄底市| 柯坪县| 崇左市| 精河县| 大方县| 元氏县| 沛县| 潮安县| 平泉县|