最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang中Slice 底層機制的實現(xiàn)

 更新時間:2026年03月04日 09:16:23   作者:Das1_  
本文主要介紹了Golang中Slice 底層機制的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1. 核心數(shù)據(jù)結構

切片本身并不存儲數(shù)據(jù),而是底層數(shù)組的一個“視圖”或描述符。其底層結構(reflect.SliceHeader)僅占用 3 個機器字長(64位系統(tǒng)為24字節(jié)):

  • Data(指針) :指向底層數(shù)組中切片起點的真實內存地址。
  • Len(長度) :切片當前可訪問的有效元素個數(shù)。
  • Cap(容量) :底層數(shù)組從 Data 指針位置開始,到其物理空間末尾的總容量。

2. Len 與 Cap 的設計哲學

相比較于C語言的數(shù)組,為什么golang中還有l(wèi)en和cap的說法,既然底層已經占據(jù)了cap的內存,len不是多此一舉嗎?

分離 Len 與 Cap 的核心目的是兼顧性能安全

  • Cap (性能緩沖) :用于向操作系統(tǒng)“批發(fā)”內存。避免頻繁的 append 操作每次都觸發(fā)高昂的系統(tǒng)調用和內存分配(平攤開銷)。
  • Len (語義與安全) :劃定有效數(shù)據(jù)的邏輯邊界。攔截對已分配但未初始化(或已廢棄)內存區(qū)域的訪問,防止臟數(shù)據(jù)泄漏。

3. 切片表達式與底層坐標系

在表達式 arr[low : high : max] 中,三個參數(shù)均代表相對于原數(shù)組的物理索引,而非直接的長度或容量數(shù)值。

  • 指針偏移:新切片的 Data 指針指向 arr[low]。low 之前的元素從新切片的視野中被永久剝離。
  • 長度計算Len = high - low
  • 容量計算Cap = max - lowmax 絕對不能超過原底層數(shù)組的最大容量)

應用場景:完整切片表達式主要用于內存隔離,限制切片的 Cap,強制其在未來 append 時觸發(fā)擴容,從而避免意外覆蓋底層數(shù)組中的后續(xù)數(shù)據(jù)。

對于max的理解

max實際上是一個相對于原數(shù)組的索引,表示slice在原數(shù)組上的最大右邊界索引,而不是直接指定新切片的容量數(shù)字。

arr[1:4:7] 時,底層其實是在說:“把索引 1 作為起點,索引 4 作為當前視口的終點,并且把索引 7 作為底層物理空間的絕對禁區(qū)(不能達到或越過索引 7)

var arr = [...]int{0, 1, 2, 3, 4, 5, 6}  
slice1 := arr[1:4:5] // 左閉右開區(qū)間,最大容量為 5
// slice1 => [1 2 3]  
fmt.Println(slice1)  
slice2 := arr[1:4:7]   
// high <= max <= cap 雖然 1 + 7 = 8 > 7=cap,但是這里不會報錯  
// slice2 => [1 2 3]  
fmt.Println(slice2)

4. 擴容機制 (Append)

切片長度增加時存在兩種截然不同的物理行為:

  • 假擴容(在 Cap 范圍內) :底層不分配任何新內存。切片僅僅是向后推移其右邊界(Len 增加),占用底層數(shù)組中預留的 Cap 空間,原地寫入新數(shù)據(jù)。
  • 真擴容(超出 Cap) :觸發(fā)內存重分配。Runtime 申請一塊全新、更大的連續(xù)內存,將舊底層數(shù)組的數(shù)據(jù)全量拷貝至新內存,追加新元素,最后將切片的 Data 指針修改為指向新內存(舊數(shù)組無引用后被 GC 收回)。

當真擴容發(fā)生時,slice追加的數(shù)組超出了原數(shù)組的cap,go內部創(chuàng)建一個新的數(shù)組,此時該slice的引用地址不再是arr

var arr = [...]int{1, 2, 3, 4}  
fmt.Println(arr) //[1 2 3 4]  
slice1 := arr[:]  
fmt.Println(slice1) //[1 2 3 4]  
slice1 = append(slice1, []int{5, 6, 7}...)  
fmt.Println(slice1) //[1 2 3 4 5 6 7]  
slice1 = append(slice1, 8)  
slice1[0] = 888  
fmt.Println(slice1) // [888 2 3 4 5 6 7 8]  
fmt.Println(arr)    // [1 2 3 4]

而假擴容時,則仍是在原數(shù)組上進行追加而已

var arr = [6]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4,0,0]
slice := arr[:4]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,5)
fmt.Println(arr) //[1,2,3,4,5,0]
fmt.Println(slice) //[1,2,3,4,5]

5. 參數(shù)傳遞機制:為何能修改原數(shù)組?

Go 語言所有參數(shù)傳遞均為嚴格的值傳遞(拷貝)

數(shù)組傳參:拷貝整個數(shù)組的全部元素(全量復?。?。在函數(shù)內修改副本,原數(shù)組毫無影響。

切片傳參:僅拷貝 SliceHeader(指針、Len、Cap 的拷貝)。

  • 表現(xiàn)為“引用”的根本原因:復印件中的 Data 指針與原件指向同一塊底層數(shù)組內存。因此修改元素會穿透到原數(shù)組。
  • 核心陷阱:在函數(shù)內對切片執(zhí)行 append,雖然可能修改底層數(shù)據(jù),但無法改變外部切片的 LenCap(因為修改的是副本里的字段)。若觸發(fā)了“真擴容”,內部切片將指向新數(shù)組,與外部徹底脫軌。

簡單來說:- 因為切片是個引用類型,所以它作為參數(shù)傳遞給函數(shù),函數(shù)操作的實質是底層數(shù)組

func main() {
	var slice = make([]int,3,5) //len=3,cap=5
	fmt.Println(slice)  //[0,0,0]
	slice2:=slice[:5]  //slice實現(xiàn)了對slice的擴容,切片長度變?yōu)?
	fmt.Println(slice2) //[0,0,0,0,0]
	slice[0] = 999  //這里slice和slice的index=0位置都是999 因為他們引用的底層數(shù)組的index=0位置都是999
	fmt.Println(slice)
	fmt.Println(slice2)
	AddOne(slice) //[8888,0,0]
	fmt.Println(slice) //[8888,0,0]
	fmt.Println(slice2) //[8888,0,0,0]
}
func AddOne(s []int){
	s[0] = 8888
	fmt.Println(s)
}

6. 對于slice 的 slice

在 Go 語言中,每一次切片操作都會建立一個 “全新的相對坐標系” 。當你對一個 slice 再次進行切片時,所有的索引(lowhigh、max)都是基于當前這個 slice 的起點(索引 0) 來計算的,它根本不關心最底層的數(shù)組是從哪里開始的。

var arr = [...]int{0, 1, 2, 3, 4, 5, 6}  
slice1 := arr[1:4:5] // 左閉右開區(qū)間,最大容量為 5
// slice1 => [1 2 3]  
slice3 := slice1[1:3:4]
fmt.Println(slice3)  
// slice3 => [2 3]  這里的從slice[1]開始
slice4 := slice1[1:4]  
// slice4 => [2 3 4]  
fmt.Println(slice4)

到此這篇關于Golang中Slice 底層機制的實現(xiàn)的文章就介紹到這了,更多相關Golang Slice底層機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • go語言的panic和recover函數(shù)用法實例

    go語言的panic和recover函數(shù)用法實例

    今天小編就為大家分享一篇關于go語言的panic和recover函數(shù)用法實例,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • golang 原生database\sql 的重連機制實現(xiàn)

    golang 原生database\sql 的重連機制實現(xiàn)

    本文主要介紹了golang 原生database\sql 的重連機制實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-02-02
  • 一篇文章帶你搞懂Go語言標準庫Time

    一篇文章帶你搞懂Go語言標準庫Time

    在我們開發(fā)的過程中,每個項目都需要時間這一類的函數(shù),此時對time這個包的研究深度就顯得尤為重要,這篇文章主要給大家介紹了關于如何通過一篇文章帶你搞懂Go語言標準庫Time的相關資料,需要的朋友可以參考下
    2022-10-10
  • Go語言實戰(zhàn)學習之流程控制詳解

    Go語言實戰(zhàn)學習之流程控制詳解

    這篇文章主要為大家詳細介紹了Go語言中的流程控制,文中的示例代碼講解詳細,對我們學習Go語言有一定的幫助?,需要的朋友可以參考下
    2022-08-08
  • Go語言基礎學習之指針詳解

    Go語言基礎學習之指針詳解

    Go 語言中指針是很容易學習的,Go 語言中使用指針可以更簡單的執(zhí)行一些任務。所以本文就來和大家聊聊Go語言中指針的定義與使用,需要的可以參考一下
    2022-12-12
  • go nil處理如何正確返回nil的error

    go nil處理如何正確返回nil的error

    這篇文章主要為大家介紹了go中的nil處理,如何正確返回nil的error實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • 解決Golang并發(fā)工具Singleflight的問題

    解決Golang并發(fā)工具Singleflight的問題

    前段時間在一個項目里使用到了分布式鎖進行共享資源的訪問限制,后來了解到Golang里還能夠使用singleflight對共享資源的訪問做限制,于是利用空余時間了解,將知識沉淀下來,并做分享
    2022-05-05
  • Go項目開發(fā)中如何讀取應用配置詳解

    Go項目開發(fā)中如何讀取應用配置詳解

    本文主要介紹了Go項目開發(fā)中如何讀取應用配置詳解,Go生態(tài)中有很多包可以加載并解析配置,最受歡迎的是Viper包,下面就來詳細的介紹一下
    2024-05-05
  • GoLang中sql.Exec()報錯解決辦法

    GoLang中sql.Exec()報錯解決辦法

    這篇文章主要給大家介紹了關于GoLang中sql.Exec()報錯的解決辦法,文中通過代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-01-01
  • Go語言MD5加密用法實例

    Go語言MD5加密用法實例

    這篇文章主要介紹了Go語言MD5加密用法,實例分析了Go語言MD5加密的使用技巧,需要的朋友可以參考下
    2015-03-03

最新評論

阿合奇县| 永昌县| 辛集市| 会同县| 资中县| 瑞昌市| 大同市| 贞丰县| 南漳县| 昔阳县| 宁乡县| 凉城县| 益阳市| 朝阳区| 遂平县| 奇台县| 信丰县| 娱乐| 将乐县| 司法| 鱼台县| 新闻| 丽水市| 柞水县| 静海县| 马鞍山市| 土默特左旗| 宜都市| 天等县| 乌鲁木齐县| 盐城市| 陆河县| 德钦县| 巩留县| 秦安县| 阜平县| 富平县| 丁青县| 库尔勒市| 屯留县| 五台县|