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

golang中值類型/指針類型的變量區(qū)別總結(jié)

 更新時(shí)間:2017年12月09日 16:45:50   作者:盧春風(fēng)  
golang的值類型和指針類型receiver一直是大家比較混淆的地方,下面這篇文章主要給大家總結(jié)介紹了關(guān)于golang中值類型/指針類型的變量區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。

前言

值類型:所有像int、float、bool和string這些類型都屬于值類型,使用這些類型的變量直接指向存在內(nèi)存中的值,值類型的變量的值存儲在棧中。當(dāng)使用等號=將一個(gè)變量的值賦給另一個(gè)變量時(shí),如 j = i ,實(shí)際上是在內(nèi)存中將 i 的值進(jìn)行了拷貝。可以通過 &i 獲取變量 i 的內(nèi)存地址

指針類型:簡單地說go語言的指針類型和C/C++的指針類型用法是一樣的,除了出去安全性的考慮,go語言增加了一些限制,包括如下幾條:

  • 不同類型的指針不能互相轉(zhuǎn)化,例如*int, int32, 以及int64
  • 任何普通指針類型*T和uintptr之間不能互相轉(zhuǎn)化
  • 指針變量不能進(jìn)行運(yùn)算, 比如C/C++里面的++, --運(yùn)算

下面將給大家詳細(xì)介紹golang中值類型/指針類型的變量的一些區(qū)別,下面話不多說了,來一起看看詳細(xì)的介紹吧。

值類型的變量和指針類型的變量

先聲明一個(gè)結(jié)構(gòu)體:

type T struct {
 Name string
}
func (t T) M1() {
 t.Name = "name1"
}
func (t *T) M2() {
 t.Name = "name2"
}

M1() 的接收者是值類型 T, M2() 的接收者是值類型 *T , 兩個(gè)方法內(nèi)都是改變Name值。

下面聲明一個(gè) T 類型的變量,并調(diào)用 M1()M2() 。

 t1 := T{"t1"}
 fmt.Println("M1調(diào)用前:", t1.Name)
 t1.M1()
 fmt.Println("M1調(diào)用后:", t1.Name)
 fmt.Println("M2調(diào)用前:", t1.Name)
 t1.M2()
 fmt.Println("M2調(diào)用后:", t1.Name)

輸出結(jié)果為:

M1調(diào)用前: t1

M1調(diào)用后: t1

M2調(diào)用前: t1

M2調(diào)用后: name2

下面猜測一下go會怎么處理。

先來約定一下:接收者可以看作是函數(shù)的第一個(gè)參數(shù),即這樣的: func M1(t T) , func M2(t *T) 。 go不是面向?qū)ο蟮恼Z言,所以用那種看起來像面向?qū)ο蟮恼Z法來理解可能有偏差。

當(dāng)調(diào)用 t1.M1() 時(shí)相當(dāng)于 M1(t1) ,實(shí)參和行參都是類型 T,可以接受。此時(shí)在M1()中的t只是t1的值拷貝,所以M1()的修改影響不到t1。

當(dāng)調(diào)用 t1.M2() => M2(t1) ,這是將 T 類型傳給了 *T 類型,go可能會取 t1 的地址傳進(jìn)去: M2(&t1) 。所以 M2() 的修改可以影響 t1 。

類型的變量這兩個(gè)方法都是擁有的。

下面聲明一個(gè) *T 類型的變量,并調(diào)用 M1()M2() 。

 t2 := &T{"t2"}
 fmt.Println("M1調(diào)用前:", t2.Name)
 t2.M1()
 fmt.Println("M1調(diào)用后:", t2.Name)
 fmt.Println("M2調(diào)用前:", t2.Name)
 t2.M2()
 fmt.Println("M2調(diào)用后:", t2.Name)

輸出結(jié)果為:

M1調(diào)用前: t2

M1調(diào)用后: t2

M2調(diào)用前: t2

M2調(diào)用后: name2

t2.M1() => M1(t2) , t2 是指針類型, 取 t2 的值并拷貝一份傳給 M1。

t2.M2() => M2(t2) ,都是指針類型,不需要轉(zhuǎn)換。

*T 類型的變量也是擁有這兩個(gè)方法的。

傳給接口會怎樣?

先聲明一個(gè)接口

type Intf interface {
 M1()
 M2()
}

使用:

 var t1 T = T{"t1"}
 t1.M1()
 t1.M2()
 var t2 Intf = t1
 t2.M1()
 t2.M2()

報(bào)錯(cuò):

./main.go:9: cannot use t1 (type T) as type Intf in assignment:

T does not implement Intf (M2 method has pointer receiver)

var t2 Intf = t1 這一行報(bào)錯(cuò)。

t1 是有 M2() 方法的,但是為什么傳給 t2 時(shí)傳不過去呢?

簡單來說,按照接口的理論:傳過去【賦值】的對象必須實(shí)現(xiàn)了接口要求的方法,而t1沒有實(shí)現(xiàn)M2() ,t1的指針實(shí)現(xiàn)了M2() 。另外和c語言一樣,函數(shù)名本身就是指針

當(dāng)把 var t2 Intf = t1 修改為 var t2 Intf = &t1 時(shí)編譯通過,此時(shí) t2 獲得的是 t1 的地址, t2.M2() 的修改可以影響到 t1 了。

如果聲明一個(gè)方法 func f(t Intf) , 參數(shù)的傳遞和上面的直接賦值是一樣的情況。

嵌套類型

聲明一個(gè)類型 S,將 T 嵌入進(jìn)去

type S struct { T }

使用下面的例子測試一下:

 t1 := T{"t1"} 
 s := S{t1} 
 fmt.Println("M1調(diào)用前:", s.Name) 
 s.M1() 
 fmt.Println("M1調(diào)用后:", s.Name) 
 fmt.Println("M2調(diào)用前:", s.Name) 
 s.M2() 
 fmt.Println("M2調(diào)用后:", s.Name) 
 fmt.Println(t1.Name)

輸出:

M1調(diào)用前: t1

M1調(diào)用后: t1

M2調(diào)用前: t1

M2調(diào)用后: name2

t1

將 T 嵌入 S, 那么 T 擁有的方法和屬性 S 也是擁有的,但是接收者卻不是 S 而是 T。

所以 s.M1() 相當(dāng)于 M1(t1) 而不是 M1(s) 。

最后 t1 的值沒有改變,因?yàn)槲覀兦度氲氖?T 類型,所以 S{t1} 的時(shí)候是將 t1 拷貝了一份。

假如我們將 s 賦值給 Intf 接口會怎么樣呢?

 var intf Intf = s 
 intf.M1() 
 intf.M2()

報(bào)錯(cuò):

cannot use s (type S) as type Intf in assignment: S does not implement Intf (M2 method has pointer receiver)

還是 M2() 的問題,因?yàn)?s 此時(shí)還是值類型。

var intf Intf = &s 這樣的話編譯通過了,如果在 intf.M2() 中改變了 Name 的值, s.Name 被改變了,但是 t1.Name 依然沒變,因?yàn)楝F(xiàn)在 t1 和 s 已經(jīng)沒有聯(lián)系了。

下面嵌入 *T 試試:

type S struct { *T }

使用時(shí)這樣:

 t1 := T{"t1"} 
 s := S{&t1} 
 fmt.Println("M1調(diào)用前:", s.Name) 
 s.M1() 
 fmt.Println("M1調(diào)用后:", s.Name) 
 fmt.Println("M2調(diào)用前:", s.Name) 
 s.M2() 
 fmt.Println("M2調(diào)用后:", s.Name) 
 fmt.Println(t1.Name)

M1調(diào)用前: t1

M1調(diào)用后: t1

M2調(diào)用前: t1

M2調(diào)用后: name2

name2

惟一的區(qū)別是最后 t1 的值變了,因?yàn)槲覀儚?fù)制的是指針。

接著賦值給接口試試:

 var intf Intf = s i
 ntf.M1() 
 intf.M2() 
 fmt.Println(s.Name)

編譯沒有報(bào)錯(cuò)。這里我們傳遞給 intf 的是值類型而不是指針,為什么可以通過呢?

拷貝 s 的時(shí)候里面的 T 是指針類型,所以調(diào)用 M2() 的時(shí)候傳遞進(jìn)去的是一個(gè)指針。

var intf Intf = &s 的效果和上面一樣。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • golang中sync.Once只執(zhí)行一次的原理解析

    golang中sync.Once只執(zhí)行一次的原理解析

    在某些場景下,我們希望某個(gè)操作或者函數(shù)僅被執(zhí)行一次,比如單例模式的初始化,一些資源配置的加載等,golang中的sync.Once就實(shí)現(xiàn)了這個(gè)功能,本文就和大家一起解析sync.Once只執(zhí)行一次的原理,需要的朋友可以參考下
    2023-09-09
  • Go語言開發(fā)k8s之Deployment操作解析

    Go語言開發(fā)k8s之Deployment操作解析

    這篇文章主要為大家介紹了Go語言開發(fā)k8s之Deployment操作解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • golang新手不注意可能會出現(xiàn)的一些小問題

    golang新手不注意可能會出現(xiàn)的一些小問題

    最近在學(xué)習(xí)golang,發(fā)現(xiàn)了一些新手們需要注意的小問題,下面這篇文章主要給大家介紹了關(guān)于golang新手不注意可能會出現(xiàn)的一些小問題,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-12-12
  • golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn)

    golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn)

    這篇文章主要介紹了golang對etcd存取和數(shù)值監(jiān)測的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 如何在golang中使用shopspring/decimal來處理精度問題

    如何在golang中使用shopspring/decimal來處理精度問題

    本文主要介紹了如何在golang中使用shopspring/decimal來處理精度問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • golang監(jiān)聽ip數(shù)據(jù)包的實(shí)現(xiàn)步驟(golang純享版)

    golang監(jiān)聽ip數(shù)據(jù)包的實(shí)現(xiàn)步驟(golang純享版)

    這篇文章主要給大家介紹了golang監(jiān)聽ip數(shù)據(jù)包的實(shí)現(xiàn)步驟,本文以ip4 作為案例進(jìn)行包抓取示范,ip6抓取與ip4方式異曲同工,可自行舉一反三得出,文中通過圖文結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • 如何利用golang運(yùn)用mysql數(shù)據(jù)庫

    如何利用golang運(yùn)用mysql數(shù)據(jù)庫

    這篇文章主要介紹了如何利用golang運(yùn)用mysql數(shù)據(jù)庫,文章對依賴包、db對象注入ApiRouter等內(nèi)容,需要的小伙伴可以參考一下
    2022-03-03
  • Go設(shè)計(jì)模式之代理模式圖文詳解

    Go設(shè)計(jì)模式之代理模式圖文詳解

    這篇文章將通過圖文講解給大家詳細(xì)的介紹一下Go代理模式,代理模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,代理控制著對于原對象的訪問, 并允許在將請求提交給對象前后進(jìn)行一些處理,感興趣的同學(xué)跟著小編一起來看看吧
    2023-07-07
  • Go 值傳遞與引用傳遞的方法

    Go 值傳遞與引用傳遞的方法

    這篇文章主要介紹了Go 值傳遞與引用傳遞的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • Go編寫定時(shí)器與定時(shí)任務(wù)詳解(附第三方庫gocron用法)

    Go編寫定時(shí)器與定時(shí)任務(wù)詳解(附第三方庫gocron用法)

    當(dāng)需要每天執(zhí)行定時(shí)任務(wù)的時(shí)候就需要定時(shí)器來處理了,周期任務(wù),倒計(jì)時(shí)任務(wù),定點(diǎn)任務(wù)等,下面這篇文章主要給大家介紹了關(guān)于Go編寫定時(shí)器與定時(shí)任務(wù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07

最新評論