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

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

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

1、概述

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

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

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

注意 1:golang 指針詳細介紹請參見《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{} ,變量是不可變的(該變量沒有地址,不能對其進行尋址操作)
}

因此,如果我們用 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 編譯器提供的語法糖!

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

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

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

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

輸出結果類似于:0xc0000120a0,表明變量 x 的內(nèi)存地址已經(jīng)被分配了。但是由于變量沒有被初始化,x 的值將為整型的默認值 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() // 編譯通過
}

輸出結果:

./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 問題總結

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

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

4、總結 

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

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

相關文章

  • Golang自旋鎖的相關介紹

    Golang自旋鎖的相關介紹

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

    Go語言上下文context底層原理

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

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

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

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

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

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

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

    關于Golang變量初始化/類型推斷/短聲明的問題

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

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

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

    Golang http包構建RESTful API的實現(xiàn)

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

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

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

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

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

最新評論