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