亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

淺談golang slice 切片原理

2020-04-01 19:02:07
字體:
來源:轉載
供稿:網友

slice介紹

數組的長度在定義之后無法再次修改;數組是值類型,每次傳遞都將產生一份副本。顯然這種數據結構無法完全滿足開發者的真實需求。在初始定義數組時,我們并不知道需要多大的數組,因此我們就需要“動態數組”。在Go里面這種數據結構叫slice,slice并不是真正意義上的動態數組,而是一個引用類型。slice總是指向一個底層array,slice的聲明也可以像array一樣,只是不需要長度,它是可變長的,可以隨時往slice里面加數據。

初看起來,數組切片就像一個指向數組的指針,實際上它擁有自己的數據結構,而不僅僅是個指針。數組切片的數據結構可以抽象為以下3個變量:

1.一個指向原生數組的指針(point):指向數組中slice指定的開始位置;
2.數組切片中的元素個數(len):即slice的長度;
3.數組切片已分配的存儲空間(cap):也就是slice開始位置到數組的最后位置的長度。

從底層實現的角度來看,數組切片實際上仍然使用數組來管理元素,基于數組,數組切片添加了一系列管理功能,可以隨時動態擴充存放空間,并且可以被隨意傳遞而不會導致所管理的元素被重復復制。

slice聲明

聲明slice時方括號[]內沒有任何數據
聲明一個元素類型為int的slice
var mySlice []int    聲明兩個元素類型為byte的slice   

golang/254224.html">golang 中的 slice 非常強大,讓數組操作非常方便高效。在開發中不定長度表示的數組全部都是 slice 。但是很多同學對 slice 的模糊認識,造成認為golang中的數組是引用類型,結果就是在實際開發中碰到很多坑,以至于出現一些莫名奇妙的問題,數組中的數據丟失了。

下面我們就開始詳細理解下 slice ,理解后會對開發出高效的程序非常有幫助。

這個是 slice 的數據結構,它很簡單,一個指向真實 array 地址的指針 ptr ,slice 的長度 len 和容量 cap 。

golang,slice,切片,go語言

其中 len 和 cap 就是我們在調用 len(slice) 和 cap(slice) 返回的值。

我們來按照 slice 的數據結構定義來解析出 ptr, len, cap

// 按照上圖定義的數據結構type Slice struct {  ptr  unsafe.Pointer    // Array pointer  len  int        // slice length  cap   int        // slice capacity}

下面寫一個完整的程序,嘗試把golang中slice的內存區域轉換成我們定義的 Slice 進行解析

package mainimport (  "fmt"  "unsafe")// 按照上圖定義的數據結構type Slice struct {  ptr unsafe.Pointer // Array pointer  len int      // slice length  cap int      // slice capacity}// 因為需要指針計算,所以需要獲取int的長度// 32位 int length = 4// 64位 int length = 8var intLen = int(unsafe.Sizeof(int(0)))func main() {  s := make([]int, 10, 20)  // 利用指針讀取 slice memory 的數據  if intLen == 4 { // 32位    m := *(*[4 + 4*2]byte)(unsafe.Pointer(&s))    fmt.Println("slice memory:", m)  } else { // 64 位    m := *(*[8 + 8*2]byte)(unsafe.Pointer(&s))    fmt.Println("slice memory:", m)  }  // 把slice轉換成自定義的 Slice struct  slice := (*Slice)(unsafe.Pointer(&s))  fmt.Println("slice struct:", slice)  fmt.Printf("ptr:%v len:%v cap:%v /n", slice.ptr, slice.len, slice.cap)  fmt.Printf("golang slice len:%v cap:%v /n", len(s), cap(s))  s[0] = 0  s[1] = 1  s[2] = 2  // 轉成數組輸出  arr := *(*[3]int)(unsafe.Pointer(slice.ptr))  fmt.Println("array values:", arr)  // 修改 slice 的 len  slice.len = 15  fmt.Println("Slice len: ", slice.len)  fmt.Println("golang slice len: ", len(s))}

運行一下查看結果

$ go run slice.goslice memory: [0 64 6 32 200 0 0 0 10 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0]slice struct: &{0xc820064000 10 20}ptr:0xc820064000 len:10 cap:20golang slice len:10 cap:20array values: [0 1 2]Slice len: 15golang slice len: 15

看到了,golang slice 的memory內容,和自定義的 Slice 的值,還有按照 slice 中的指針指向的內存,就是實際 Array 數據。當修改了 slice 中的len, len(s) 也變了。

接下來結合幾個例子,了解下slice一些用法

聲明一個Array通常使用 make ,可以傳入2個參數,也可傳入3個參數,第一個是數據類型,第二個是 len ,第三個是 cap 。如果不穿入第三個參數,則 cap=len ,append 可以用來向數組末尾追加數據。

這是一個 append 的測試

// 每次cap改變,指向array的ptr就會變化一次s := make([]int, 1)fmt.Printf("len:%d cap: %d array ptr: %v /n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))for i := 0; i < 5; i++ {  s = append(s, i)  fmt.Printf("len:%d cap: %d array ptr: %v /n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))}fmt.Println("Array:", s)

運行結果

len:1 cap: 1 array ptr: 0xc8200640f0len:2 cap: 2 array ptr: 0xc820064110len:3 cap: 4 array ptr: 0xc8200680c0len:4 cap: 4 array ptr: 0xc8200680c0len:5 cap: 8 array ptr: 0xc82006c080len:6 cap: 8 array ptr: 0xc82006c080Array: [0 0 1 2 3 4]

看出來了吧,每次cap改變的時候指向array內存的指針都在變化。當在使用 append 的時候,如果 cap==len 了這個時候就會新開辟一塊更大內存,然后把之前的數據復制過去。

實際go在append的時候放大cap是有規律的。在 cap 小于1024的情況下是每次擴大到 2 * cap ,當大于1024之后就每次擴大到 1.25 * cap 。所以上面的測試中cap變化是 1, 2, 4, 8

在實際使用中,我們最好事先預期好一個cap,這樣在使用append的時候可以避免反復重新分配內存復制之前的數據,減少不必要的性能消耗。

創建切片

s := []int{1, 2, 3, 4, 5}fmt.Printf("len:%d cap: %d array ptr: %v /n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))fmt.Println("Array:", s)s1 := s[1:3]fmt.Printf("len:%d cap: %d array ptr: %v /n", len(s1), cap(s1), *(*unsafe.Pointer)(unsafe.Pointer(&s1)))fmt.Println("Array", s1)

運行結果

len:5 cap: 5 array ptr: 0xc820012210Array: [1 2 3 4 5]len:2 cap: 4 array ptr: 0xc820012218Array [2 3]

在一個切片基礎上創建新的切片 s1 ,新切片的 ptr 指向的就是 s1[0] 數據的內存地址。可以看到指針地址 0xc820012210 與 0xc820012218 相差 8byte 正好是一個int類型長度,cap也相應的變為4

就寫到這里了,總結一下,切片的結構是指向數據的指針,長度和容量。復制切片,或者在切片上創建新切片,切片中的指針都指向相同的數據內存區域。

知道了切片原理就可以在開發中避免出現錯誤了,希望這篇博客可以給大家帶來幫助。也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
高清日韩电视剧大全免费播放在线观看| 在线免费看av不卡| 国产成人亚洲综合青青| 久久91亚洲精品中文字幕奶水| 国产999视频| 亚洲激情电影中文字幕| 日韩免费观看av| 欧美专区国产专区| 久久久www成人免费精品张筱雨| 亚洲自拍av在线| 国产精品免费小视频| 中文字幕日韩欧美在线| 成人高清视频观看www| 国产精品日日摸夜夜添夜夜av| 黑丝美女久久久| 成人免费网站在线| 一区国产精品视频| 亚洲欧美日韩精品久久| 欧美在线欧美在线| 久久久久久久久久久网站| 亚洲人成77777在线观看网| 亚洲国产精久久久久久久| 久久久亚洲影院你懂的| 日韩欧美一区二区三区| 97久久久免费福利网址| 国产欧美一区二区三区久久| 欧美与黑人午夜性猛交久久久| 久久精品国产99国产精品澳门| 久久香蕉国产线看观看网| 亚洲男人天堂网站| 久久久久久亚洲精品中文字幕| 性色av一区二区咪爱| 97涩涩爰在线观看亚洲| www.日韩免费| 91精品国产乱码久久久久久久久| 欧美高清性猛交| 国产精品久久久久久久天堂| 91精品中文在线| 国产欧美在线观看| 91日本在线视频| 欧美精品在线免费| 亚洲热线99精品视频| 久久久91精品国产一区不卡| 亚洲欧美国产精品| 欧美成人午夜剧场免费观看| 日韩美女免费视频| 成人网在线免费观看| 最新亚洲国产精品| 91av在线影院| 国产精品扒开腿爽爽爽视频| 国产网站欧美日韩免费精品在线观看| 日韩精品视频在线| 欧美精品日韩www.p站| 久久国内精品一国内精品| 久久久久久亚洲精品中文字幕| 亚洲精品国产精品国产自| 国产在线98福利播放视频| 欧美日韩一二三四五区| 成人中心免费视频| 国产精品wwwwww| 青青a在线精品免费观看| 国产精品久久久久久久久久东京| 精品成人在线视频| 国产精品v日韩精品| 欧美福利视频在线| 欧美性视频网站| 中文字幕精品国产| 精品久久久久久久久久久| 精品国产乱码久久久久久天美| 欧美成人精品不卡视频在线观看| 97人洗澡人人免费公开视频碰碰碰| 国产日产欧美精品| 欧美激情综合亚洲一二区| 精品动漫一区二区三区| 国模视频一区二区三区| 久久久久久久久久久人体| 全球成人中文在线| 国产综合视频在线观看| 欧美老妇交乱视频| 亚洲精品99久久久久| 成人网在线免费看| 国产一区二区视频在线观看| 国内偷自视频区视频综合| 国产精品久久久久久久av大片| 亚洲最大成人在线| 国产精品网红直播| 中文字幕国产精品久久| 成年人精品视频| 久久影视三级福利片| 国产成人精品电影| 日韩av最新在线| 精品国产美女在线| 亚洲国产古装精品网站| 中文字幕最新精品| 欧美日韩免费观看中文| 日韩av电影中文字幕| 亚洲最新av网址| 成人精品在线视频| 日韩在线视频观看| 国产精品av电影| 日韩中文字幕免费看| 亚洲福利视频久久| 亚洲精品一区二区在线| 在线观看中文字幕亚洲| 日韩欧美一区二区三区久久| 欧美性精品220| 中文字幕精品网| 国产美女搞久久| 九九综合九九综合| 欧美大学生性色视频| zzijzzij亚洲日本成熟少妇| 国产日韩在线精品av| 亚洲激情在线观看视频免费| 国产精品wwww| 精品国产31久久久久久| 亚洲一区二区三区视频| 51精品在线观看| 色777狠狠综合秋免鲁丝| 91精品国产91| 超碰精品一区二区三区乱码| 日本精品中文字幕| 在线看日韩av| 国内伊人久久久久久网站视频| 国产一级揄自揄精品视频| 中文字幕久热精品视频在线| 亚洲精品永久免费精品| 91av在线网站| 成人久久一区二区三区| 欧美大尺度激情区在线播放| 韩国日本不卡在线| 韩国v欧美v日本v亚洲| 懂色av影视一区二区三区| 亚洲欧美日韩一区二区三区在线| 亚洲欧美一区二区激情| 1769国产精品| 久久偷看各类女兵18女厕嘘嘘| 久久精品福利视频| 色噜噜久久综合伊人一本| 欧美性色视频在线| 国产日产欧美a一级在线| 国产精品成人免费视频| 精品国产老师黑色丝袜高跟鞋| 91免费视频网站| 久久久免费高清电视剧观看| 中文字幕欧美日韩va免费视频| 美女国内精品自产拍在线播放| 国产97色在线|日韩| 欧美剧在线观看| 国产在线999| 4438全国亚洲精品在线观看视频| 日韩美女写真福利在线观看| 在线观看国产成人av片| 国产精品久久久久久中文字| 欧美尺度大的性做爰视频| 亚洲欧美日韩一区二区在线| 久久久精品电影| 91久久综合亚洲鲁鲁五月天| 国产精品亚洲激情| 国产精品第一区| 亚洲精品一区久久久久久| 日韩av综合中文字幕| 久久精品亚洲94久久精品| 国产一区二区丝袜| 亚洲精品按摩视频|