校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > 淺談golang slice 切片原理

淺談golang slice 切片原理

熱門標簽:汕頭小型外呼系統 濱州自動電銷機器人排名 建造者2地圖標注 阿里云ai電話機器人 釘釘有地圖標注功能嗎 鄭州亮點科技用的什么外呼系統 浙江高頻外呼系統多少錢一個月 黃岡人工智能電銷機器人哪個好 惠州電銷防封電話卡

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

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

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

其中 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 main

import (
  "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 = 8
var 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.go

slice 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:20
golang slice len:10 cap:20
array values: [0 1 2]
Slice len: 15
golang 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: 0xc8200640f0
len:2 cap: 2 array ptr: 0xc820064110
len:3 cap: 4 array ptr: 0xc8200680c0
len:4 cap: 4 array ptr: 0xc8200680c0
len:5 cap: 8 array ptr: 0xc82006c080
len:6 cap: 8 array ptr: 0xc82006c080
Array: [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: 0xc820012210
Array: [1 2 3 4 5]
len:2 cap: 4 array ptr: 0xc820012218
Array [2 3]

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

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

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

您可能感興趣的文章:
  • golang常用手冊之切片(Slice)原理
  • Golang slice切片操作之切片的追加、刪除、插入等
  • 理解Golang中的數組(array)、切片(slice)和map
  • golang-切片slice的創建方式

標簽:瀘州 滄州 昭通 晉中 阿壩 泰安 駐馬店 東營

巨人網絡通訊聲明:本文標題《淺談golang slice 切片原理》,本文關鍵詞  淺談,golang,slice,切片,原理,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《淺談golang slice 切片原理》相關的同類信息!
  • 本頁收集關于淺談golang slice 切片原理的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    成人激情动漫在线观看| 色哟哟一区二区在线观看| 99精品欧美一区| 中文字幕一区不卡| 91福利视频在线| 欧美aaaaaa午夜精品| 精品伦理精品一区| 成人夜色视频网站在线观看| 国产精品国模大尺度视频| 99r精品视频| 亚洲天堂免费在线观看视频| 欧美日韩激情一区二区| 国产成人精品免费网站| 亚洲欧美日韩在线| 欧美成人精品二区三区99精品| 国产在线视视频有精品| 亚洲伊人色欲综合网| 欧美本精品男人aⅴ天堂| 91久久国产最好的精华液| 美脚の诱脚舐め脚责91| 亚洲欧美电影院| 欧美激情一区二区三区四区| 正在播放亚洲一区| 色狠狠色噜噜噜综合网| 成人午夜av电影| 国产一二三精品| 精品一区二区日韩| 美腿丝袜亚洲综合| 婷婷综合五月天| 五月激情六月综合| 午夜国产不卡在线观看视频| 一区二区理论电影在线观看| 精品久久久久久久久久久久久久久久久 | 6080午夜不卡| 欧美一级高清片| 精品国产91乱码一区二区三区| 不卡在线视频中文字幕| 91首页免费视频| 91在线观看污| 91国偷自产一区二区三区观看| 成人高清在线视频| av在线一区二区三区| 色婷婷精品大视频在线蜜桃视频 | 秋霞午夜av一区二区三区| 欧美一级片免费看| 欧美一区二区成人| 欧美大片一区二区三区| 久久久久久久精| 一区二区三区在线观看欧美| 亚洲综合色噜噜狠狠| 极品美女销魂一区二区三区 | 日韩欧美一区二区免费| 国产精品欧美久久久久无广告 | 久久影音资源网| 亚洲免费视频中文字幕| 国产麻豆一精品一av一免费| 一本一道久久a久久精品| 日本高清无吗v一区| 精品免费一区二区三区| 亚洲国产日韩a在线播放性色| 黑人精品欧美一区二区蜜桃 | 国产麻豆精品在线| 欧美日韩三级在线| 一区二区三区在线观看欧美| 国产精品亚洲一区二区三区在线| 欧美日本乱大交xxxxx| 亚洲欧美日韩国产手机在线| 精品一区二区三区久久久| 欧美伦理影视网| 午夜视频在线观看一区二区 | 欧美性大战久久| 亚洲欧美日本在线| 91在线播放网址| 亚洲美女精品一区| 色婷婷av久久久久久久| 尤物视频一区二区| 欧美在线免费播放| 午夜亚洲国产au精品一区二区| 99国产一区二区三精品乱码| 亚洲欧美激情在线| 99国产精品99久久久久久| 亚洲精品视频一区| 日本久久电影网| 日本美女视频一区二区| 精品久久久三级丝袜| 成人免费观看av| 夜色激情一区二区| 日韩一级黄色大片| 国产成人精品免费| 亚洲精品少妇30p| 欧美高清视频不卡网| 国产99一区视频免费| 一区二区视频在线看| 亚洲精品一区二区三区精华液| 国产东北露脸精品视频| 亚洲人亚洲人成电影网站色| 欧美三级韩国三级日本三斤| 久久不见久久见中文字幕免费| 久久在线观看免费| 欧美挠脚心视频网站| 亚洲成人三级小说| 欧美电影一区二区三区| www.一区二区| 国产一区二区三区四| 日日骚欧美日韩| 一区二区三区免费| 久久人人97超碰com| 色综合婷婷久久| 国内精品国产成人| 久久99久久99小草精品免视看| 亚洲精品一区二区三区蜜桃下载| 在线国产亚洲欧美| 国产·精品毛片| 国产成人欧美日韩在线电影| 午夜伦理一区二区| 三级欧美在线一区| 亚洲一二三专区| 一区二区欧美视频| 亚洲视频免费看| 1024国产精品| 一区二区三区精品| 三级不卡在线观看| 日本中文字幕一区二区有限公司| 亚洲三级理论片| 亚洲一线二线三线视频| 午夜精品久久久久久久久| 免费xxxx性欧美18vr| 久久精品国产**网站演员| 国产精品亚洲午夜一区二区三区| 国产精品一区在线观看乱码| 成人免费观看视频| 欧美精品粉嫩高潮一区二区| 欧美va在线播放| 一区二区在线免费观看| 蜜桃视频一区二区| 国产成人av资源| 日韩欧美综合一区| 亚洲特黄一级片| 久久99久久久欧美国产| 91亚洲国产成人精品一区二区三| 在线观看免费成人| 国产精品久久免费看| 午夜欧美电影在线观看| 91免费版pro下载短视频| 精品福利av导航| 亚洲超碰精品一区二区| 99久久精品国产观看| 欧美电影免费观看完整版| 一区二区久久久久久| 成人av资源在线观看| 欧美一区午夜精品| 亚洲国产aⅴ天堂久久| 91麻豆123| 亚洲裸体在线观看| 成人avav在线| 久久蜜桃av一区二区天堂| 免费视频一区二区| 7878成人国产在线观看| 亚洲中国最大av网站| 欧美日韩一二三| 天堂精品中文字幕在线| 欧美日韩久久不卡| 肉色丝袜一区二区| 欧美高清激情brazzers| 免费一级片91| 亚洲国产高清aⅴ视频| 成人av网站大全| 亚洲午夜影视影院在线观看| 欧美日韩国产成人在线91| 日韩黄色免费电影| 久久亚区不卡日本| 日本高清不卡视频| 日本中文字幕一区二区视频| 日韩美女在线视频| 99久久精品国产导航| 亚洲成人综合在线| 久久久久国产一区二区三区四区 | 一区二区三区欧美日| 欧美体内she精高潮| 狠狠色狠狠色综合日日91app| 国产精品国产成人国产三级 | 久久国产免费看| 亚洲激情自拍视频| 久久亚洲精精品中文字幕早川悠里 | 成人在线视频一区| 蜜桃av一区二区在线观看| 国产精品欧美经典| 26uuuu精品一区二区| 国产一区二区三区四区在线观看 | 91猫先生在线| 国产一区二区三区久久悠悠色av| 一区二区三区精密机械公司| 精品久久久久久久久久久院品网| 在线影院国内精品| 99久久精品国产麻豆演员表| 国产99久久久精品| 国产真实乱偷精品视频免| 免费观看一级欧美片| 午夜精品久久久久久久久久| 亚洲国产精品自拍|