一篇學(xué)會深拷貝和淺拷貝
1. 什么是拷貝?
當(dāng)你把 a 變量賦值給 b 變量時,其實就是把 a 變量拷貝給 b 變量
- a := "hello"
- b := a
這只是拷貝最簡單的一種形式,而有些形式卻表現(xiàn)得非常的隱蔽。比如:
- 你往一個函數(shù)中傳參
- 你向通道中傳入對象
這些其實在 Go編譯器中都會進(jìn)行拷貝的動作。
2. 什么是深淺拷貝?
知道了什么是拷貝,那我們再往深點開挖,聊聊深淺拷貝。
不過先別急,咱先了解下數(shù)據(jù)結(jié)構(gòu)的兩種類型:
值類型 :String,Array,Int,Struct,F(xiàn)loat,Bool
引用類型:Slice,Map
這兩種不同的類型在拷貝的時候,在拷貝的時候效果是完全不一樣的,這對于很多新手可能是一個坑。
對于值類型來說,你的每一次拷貝,Go 都會新申請一塊內(nèi)存空間,來存儲它的值,改變其中一個變量,并不會影響另一個變量。
- func main() {
- aArr := [3]int{0,1,2}
- fmt.Printf("打印 aArr: %v \n", aArr)
- bArr := aArr
- aArr[0] = 88
- fmt.Println("將 aArr 拷貝給 bArr 后,并修改 aArr[0] = 88")
- fmt.Printf("打印 aArr: %v \n", aArr)
- fmt.Printf("打印 bArr: %v \n", bArr)
- }
從輸出結(jié)果來看,aArr 和 bArr 相互獨立,互不干擾
- 打印 aArr: [0 1 2]
- 將 aArr 拷貝給 bArr 后,并修改 aArr[0] = 88
- 打印 aArr: [88 1 2]
- 打印 bArr: [0 1 2]
對于引用類型來說,你的每一次拷貝,Go 不會申請新的內(nèi)存空間,而是使用它的指針,兩個變量名其實都指向同一塊內(nèi)存空間,改變其中一個變量,會直接影響另一個變量。
- func main() {
- aslice := []int{0,1,2}
- fmt.Printf("打印 aslice: %v \n", aslice)
- bslice := aslice
- aslice[0] = 88
- fmt.Println("將 aslice 拷貝給 bslice 后,并修改 aslice[0] = 88")
- fmt.Printf("打印 aslice: %v \n", aslice)
- fmt.Printf("打印 bslice: %v \n", bslice)
- }
從輸出結(jié)果來看,aslice 的更新直接反映到了 bslice 的值。
- 打印 aslice: [0 1 2]
- 將 aslice 拷貝給 bslice 后,并修改 aslice[0] = 88
- 打印 aslice: [88 1 2]
- 打印 bslice: [88 1 2]
是不是很簡單?跟著明哥一起來攻克 Go 的各個邊邊角角的知識吧
加油噢,我們下篇見
本文轉(zhuǎn)載自微信公眾號「Go編程時光」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Go編程時光公眾號。