成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

看完這期圖解,別再搞不清切片拷貝了

開發 后端
在剛使用 Go 時,菜刀曾將 Python 深拷貝手法[:]用于 Go 中 ,結果造成了 bug。相信不少轉語言的 Gopher 也在切片拷貝上栽過跟頭。

[[438643]]

本文轉載自微信公眾號「Golang技術分享」,作者機器鈴砍菜刀 。轉載本文請聯系Golang技術分享公眾號。

在剛使用 Go 時,菜刀曾將 Python 深拷貝手法[:]用于 Go 中 ,結果造成了 bug。相信不少轉語言的 Gopher 也在切片拷貝上栽過跟頭。

切片是 Go 中最基礎的數據結構,之前我們談過切片傳遞、切換轉換、切片擴容等內容。

本文,我們將探討切片拷貝,就切片的三種拷貝方式進行圖解分析,希望幫助讀者鞏固一下基礎知識。

深淺拷貝

所謂深淺拷貝,其實都是進行復制,主要區別在于復制出來的新對象和原來的對象,它們的數據發生改變時,是否會相互影響。

簡單而言,B 復制 A,如果 A 的數據發生變化,B 也跟著變化,這是淺拷貝。反之, 如果 B 不發生變化,則為深拷貝。

深淺拷貝差異的根本原因在于,復制出來的對象與原對象是否會指向同一個地址。

以下是 Python 中 list 與 Go 中 slice 深淺拷貝的表現差異

  1. // Python 版 
  2. if __name__ == '__main__'
  3.     a = [1, 2, 3] 
  4.     b = a 
  5.     c = a[:] 
  6.     a[0] = 100 
  7.     print(a, b, c) // [100, 2, 3] [100, 2, 3] [1, 2, 3] 
  8.  
  9. // Golang 版 
  10. func main() { 
  11.  a := []int{1, 2, 3} 
  12.  b := a 
  13.  c := a[:] 
  14.  a[0] = 100 
  15.  fmt.Println(a, b, c) // [100 2 3] [100 2 3] [100 2 3] 

發現沒有?在 Go 中 [:] 操作并不是深拷貝。

= 拷貝

通過=操作符拷貝切片,這是淺拷貝。

  1. func main() { 
  2.  a := []int{1, 2, 3} 
  3.  b := a 
  4.  fmt.Println(unsafe.Pointer(&a))  // 0xc00000c030 
  5.  fmt.Println(a, &a[0])            // [100 2 3] 0xc00001a078 
  6.  fmt.Println(unsafe.Pointer(&b))  // 0xc00000c048 
  7.  fmt.Println(b, &b[0])            // [100 2 3] 0xc00001a078 

圖解

[:] 拷貝

通過[:]方式復制切片,同樣是淺拷貝。

  1. func main() { 
  2.  a := []int{1, 2, 3} 
  3.  b := a[:] 
  4.  fmt.Println(unsafe.Pointer(&a)) // 0xc0000a4018 
  5.  fmt.Println(a, &a[0])           // [1 2 3] 0xc0000b4000 
  6.  fmt.Println(unsafe.Pointer(&b)) // 0xc0000a4030 
  7.  fmt.Println(b, &b[0])           // [1 2 3] 0xc0000b4000 

圖解

我們有時會使用[start: end]進行拷貝。例如,b:=a[1:],那它的拷貝情況如何

copy() 拷貝

上述兩種方式都是淺拷貝,如果要切片深拷貝,需要用到copy()內置函數。

copy()函數簽名如下

  1. func copy(dst, src []Type) int 

其返回值代表切片中被拷貝的元素個數

  1. func main() { 
  2.  a := []int{1, 2, 3} 
  3.  b := make([]int, len(a), len(a)) 
  4.  copy(b, a) 
  5.  fmt.Println(unsafe.Pointer(&a))  // 0xc00000c030 
  6.  fmt.Println(a, &a[0])            // [1 2 3] 0xc00001a078 
  7.  fmt.Println(unsafe.Pointer(&b))  // 0xc00000c048 
  8.  fmt.Println(b, &b[0])            // [1 2 3] 0xc00001a090 

圖解

copy 的元素數量與原始切片和目標切片的大小、容量有關系

  1. func main() { 
  2.  a := []int{1, 2, 3} 
  3.  b := []int{-1, -2, -3, -4} 
  4.  copy(b, a) 
  5.  fmt.Println(unsafe.Pointer(&a))  // 0xc0000a4018 
  6.  fmt.Println(a, &a[0])            // [1 2 3] 0xc0000b4000 
  7.  fmt.Println(unsafe.Pointer(&b))  // 0xc0000a4030 
  8.  fmt.Println(b, &b[0])            // [1 2 3 -4] 0xc0000aa060 

圖解

總結

切片是 Go 語言中最基本的數據結構,它的擴容與拷貝細節,在理解不當時,是很容易寫出程序 bug 的。

本文分別就切片的三種拷貝方式,=、[:]、copy()進行了探討。其中,=、[:]是淺拷貝,copy()拷貝是深拷貝。

 

這樣的圖解方式,你喜歡嗎~

 

責任編輯:武曉燕 來源: Golang技術分享
相關推薦

2017-08-09 15:07:08

大數據數據分析戶畫像

2021-06-16 00:57:16

JVM加載機制

2021-02-24 07:38:50

Redis

2025-04-21 10:43:21

2020-12-04 10:05:00

Pythonprint代碼

2021-03-18 23:28:45

Python反斜杠字符串

2015-02-28 10:01:00

云計算IT架構虛擬化

2022-05-27 21:56:55

索引存儲MySQL 存儲引擎

2025-05-19 04:00:00

2020-12-01 11:33:57

Python拷貝copy

2024-12-05 11:03:04

2020-12-02 11:18:50

print調試代碼Python

2023-08-18 15:22:54

工業物聯網工業互聯網

2020-06-18 10:48:44

Linux 系統 數據

2017-08-16 09:55:36

2025-06-10 02:22:00

2018-09-28 05:25:53

TopK算法代碼

2021-06-09 06:41:11

OFFSETLIMIT分頁

2025-02-05 08:02:31

Winform開發窗體

2020-06-15 08:12:51

try catch代碼處理器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产99精品 | www.日韩 | 日韩视频二区 | 国产欧美精品一区二区三区 | 精品在线播放 | 91精品国产一区二区三区动漫 | 天天爱av| 99精品视频免费观看 | 黄色一级大片在线免费看产 | 久久国产精品精品国产色婷婷 | 日本免费一区二区三区视频 | 黄色毛片免费视频 | 羞羞视频网站免费观看 | 福利精品在线观看 | 国产视频一区二区 | 射欧美 | www.97国产| 精国产品一区二区三区四季综 | 国产一区二区三区视频 | 拍拍无遮挡人做人爱视频免费观看 | 亚洲国产精品区 | 日本色综合 | 久久久tv | 国产精品久久精品 | 免费成人高清在线视频 | 亚洲免费视频网址 | 国产2区 | 黄色一级大片在线免费看产 | 人操人免费视频 | 黄色网址在线免费观看 | 97av视频| 国产成人精品免费 | 91精品一区 | 亚洲精品一区二区三区在线 | 日韩中文字幕在线观看 | 丁香久久| 国产一区二区在线播放 | av毛片| 国产亚洲一区二区三区 | 中文字幕一区二区三区不卡 | 久久久久久国产精品mv |