Go語言中的值類型和引用類型

最本質的區別

值類型:內存中變量存儲的是具體的值 比如: var num int num存放的是具體的int值

但是變量在內存中的地址可以通過 &num 來獲取

引用類型:變量直接存放的就是一個地址值,這個地址值指向的空間存的纔是值。

例如:

 var ptr *int =& num

值類型,引用類型都包括哪些

基本的數據類型 int系列,float系列,bool,string, 數組和結構體struct

引用類型包括指針,slice切片,map ,chan ,interface

值類型和引用類型的使用特點

值類型 直接存放值,內存通常在棧中分配

應用類型變量存儲的地址(也就是通過指針訪問類型裏面的數據),通常真正的值在堆上分配。當麼有變量引用這個地址的時候,該值會被gc回收。

實例詳解值類型和引用類型

1.數組array和切片slice的實例:

定義了一個數組a,它是值類型,複製給b是copy,當b發生變化後a並不會發生任何變化,程序的執行結果如下所示:

func main() {
	a :=[5]int{1,2,3,4,5}
	b := a
	b[2] = 8
	fmt.Println(a, b) //[1,2,3,4,5] [1,2,8,4,5]
}

切片卻相反

func main() {
	a :=[]int{1,2,3,4,5}
	b := a
	b[2] = 8
	fmt.Println(a, b) //[1,2,8,4,5] [1,2,8,4,5]
}

2.來一個更復雜的例子,結構體和map

//Count代表計數器的類型
type Counter struct {
	count int
}

func add1(s map[string]int)  {
	s["count"]++
}

func add2(s map[string]Counter)  {
	counter := s["count"]
	counter.count++
}

func add3(s map[string]*Counter)  {
	counter := s["count"]
	counter.count++
}

func add4(s Counter) {
	s.count++
}

func main() {
	m1 := make(map[string]int)
	add1(m1)
	add1(m1)
	println(m1["count"])
	m2 := map[string]Counter{"count":Counter{20}}
	add2(m2)
	//temp := m2["count"]
	//temp.count++
	println(m2["count"].count)
	m3 := map[string]*Counter{"count":&Counter{20}}
	add3(m3)
	println(m3["count"].count)
	m4 := Counter{20}
	add4(m4)
	println(m4.count)
}

結果爲:

2
20
21
20

首先明確結構體是值類型,map是引用類型。

我們按m1,m4,m2,m3的順序來講解。

m1 是一個從string到int,聲明的時候進行了零初始化,也就是一開始默認值爲0。由於m1是一個引用類型,所以傳遞給add1的時候會拷貝其底層數據的指針,然後在然後通過指針直接進行操作。

而m4是一個結構體,是值類型。所以傳遞給add4的時候,是對其內存上的值拷貝,也就是add4中的s所在的內存塊跟m4不一樣了。因此,在add4中的任何操作並不會對m4造成影響。

m2,m3是結構體和map的結合。

m2不會改變,主要是因爲add2中使用:=重新聲明瞭counter,由於是對象是值類型,所以也就類似於第一個實例那樣,只是單純的進行了值拷貝。

m3是的add3中雖然看起來一樣。但實際上counter是一個指針,所以對counter進行操作會導致原來的數值也發生改變。


撩我?
我的公衆號:Kyda
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章