欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

1、概述

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

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

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

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

2、接收者方法語法糖

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3、深入測(cè)試

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)一個(gè)變量是可變的(也就是說,該變量是一個(gè)具有地址的變量,我們可以對(duì)其進(jìn)行尋址操作),我們可以通過對(duì)該變量的指針進(jìn)行方法調(diào)用來執(zhí)行對(duì)該變量的操作,否則就會(huì)導(dǎo)致編譯錯(cuò)誤。

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

相關(guān)文章

  • Golang自旋鎖的相關(guān)介紹

    Golang自旋鎖的相關(guān)介紹

    自旋鎖是指當(dāng)一個(gè)線程在獲取鎖的時(shí)候,如果鎖已經(jīng)被其他線程獲取,那么該線程將循環(huán)等待,然后不斷地判斷是否能夠被成功獲取,知直到獲取到鎖才會(huì)退出循環(huán)
    2022-10-10
  • Go語言上下文context底層原理

    Go語言上下文context底層原理

    這篇文章主要介紹了Go語言上下文context底層原理,context是Go中用來進(jìn)程通信的一種方式,其底層是借助channl與snyc.Mutex實(shí)現(xiàn)的,更多相關(guān)內(nèi)容需要的小伙伴可以參加一下
    2022-06-06
  • Go語言編譯程序從后臺(tái)運(yùn)行,不出現(xiàn)dos窗口的操作

    Go語言編譯程序從后臺(tái)運(yùn)行,不出現(xiàn)dos窗口的操作

    這篇文章主要介紹了Go語言編譯程序從后臺(tái)運(yùn)行,不出現(xiàn)dos窗口的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go語言學(xué)習(xí)之將mp4通過rtmp推送流媒體服務(wù)的實(shí)現(xiàn)方法

    Go語言學(xué)習(xí)之將mp4通過rtmp推送流媒體服務(wù)的實(shí)現(xiàn)方法

    對(duì)音視頻一直是小白,決定沉下心來,好好研究一下音視頻知識(shí),下面這篇文章主要給大家介紹了關(guān)于Go語言學(xué)習(xí)之將mp4通過rtmp推送流媒體服務(wù)的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2022-12-12
  • Golang中interface轉(zhuǎn)string輸出打印方法

    Golang中interface轉(zhuǎn)string輸出打印方法

    這篇文章主要給大家介紹了關(guān)于Golang中interface轉(zhuǎn)string輸出打印的相關(guān)資料,在go語言中interface轉(zhuǎn)string可以直接使用fmt提供的fmt函數(shù),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • 關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    這篇文章主要介紹了關(guān)于Golang變量初始化/類型推斷/短聲明的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 使用Go語言實(shí)現(xiàn)Yaml編碼和解碼的方法詳解

    使用Go語言實(shí)現(xiàn)Yaml編碼和解碼的方法詳解

    在這篇文章中,我們將介紹如何使用Go語言編寫代碼來實(shí)現(xiàn)Yaml編碼和解碼,文中有詳細(xì)的代碼示例供大家參考,對(duì)大家的學(xué)習(xí)和工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • Golang http包構(gòu)建RESTful API的實(shí)現(xiàn)

    Golang http包構(gòu)建RESTful API的實(shí)現(xiàn)

    在Go語言中實(shí)現(xiàn)RESTful API可以利用標(biāo)準(zhǔn)庫net/http提供的功能,它允許你輕松地創(chuàng)建和處理HTTP請(qǐng)求,本文主要介紹了Golang http包構(gòu)建RESTful API的實(shí)現(xiàn),感興趣的可以了解一下
    2024-01-01
  • 本地使用Docker搭建go開發(fā)環(huán)境的全過程

    本地使用Docker搭建go開發(fā)環(huán)境的全過程

    最近想學(xué)習(xí)一下golang,自己之前一直把環(huán)境全部安裝在docker上,所以這次也想把golang的環(huán)境安裝在docker上,下面這篇文章主要給大家介紹了關(guān)于本地使用Docker搭建go開發(fā)環(huán)境的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • Go實(shí)現(xiàn)比較時(shí)間大小

    Go實(shí)現(xiàn)比較時(shí)間大小

    這篇文章主要介紹了Go實(shí)現(xiàn)比較時(shí)間大小的方法和示例,非常的簡單實(shí)用,有需要的小伙伴可以參考下。
    2015-04-04

最新評(píng)論