欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)示例

 更新時(shí)間:2024年10月16日 10:52:40   作者:勇者無(wú)畏404  
動(dòng)態(tài)數(shù)組能自動(dòng)調(diào)整大小,與靜態(tài)數(shù)組不同,其大小不固定,可根據(jù)需求變化,實(shí)現(xiàn)通常依賴于數(shù)據(jù)結(jié)構(gòu)如鏈表或數(shù)組加額外信息,本文就來(lái)介紹一下Golang動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)示例,感興趣的可以了解一下

什么是動(dòng)態(tài)數(shù)組

動(dòng)態(tài)數(shù)組(Dynamic Array)是一種在需要時(shí)能夠自動(dòng)改變其大小的數(shù)組。與靜態(tài)數(shù)組(Static Array)不同,靜態(tài)數(shù)組的大小在聲明時(shí)就已確定,且之后不能更改,而動(dòng)態(tài)數(shù)組的大小則是根據(jù)需要?jiǎng)討B(tài)變化的。動(dòng)態(tài)數(shù)組通常通過(guò)某種數(shù)據(jù)結(jié)構(gòu)(如鏈表、數(shù)組加額外信息等)來(lái)實(shí)現(xiàn),以便在需要時(shí)能夠擴(kuò)展或縮小其容量。(關(guān)鍵字:動(dòng)態(tài)擴(kuò)縮容,基于鏈表或數(shù)組實(shí)現(xiàn))

在大多數(shù)現(xiàn)代編程語(yǔ)言中,如C++的std::vector、Java的ArrayList、Python的列表(list)等,都提供了動(dòng)態(tài)數(shù)組的功能。這些實(shí)現(xiàn)通常會(huì)在內(nèi)部使用一個(gè)靜態(tài)數(shù)組來(lái)存儲(chǔ)元素,并跟蹤當(dāng)前數(shù)組的大小和已分配的容量。當(dāng)向動(dòng)態(tài)數(shù)組添加元素而當(dāng)前容量不足時(shí),它們會(huì)自動(dòng)分配一個(gè)新的、更大的數(shù)組,并將舊數(shù)組的元素復(fù)制到新數(shù)組中,然后再添加新元素。這個(gè)過(guò)程對(duì)用戶是透明的,用戶無(wú)需關(guān)心底層的內(nèi)存管理細(xì)節(jié)。

Go語(yǔ)言中的動(dòng)態(tài)數(shù)組——切片(slice)

Go語(yǔ)言(Golang)中的切片(slice)是一種引用類型,它提供了對(duì)數(shù)組的抽象。切片是對(duì)數(shù)組一個(gè)連續(xù)片段的引用,但它比數(shù)組更靈活、更強(qiáng)大。以下是Go語(yǔ)言切片的一些主要特點(diǎn):

  • 動(dòng)態(tài)數(shù)組:切片的大小不是固定的,它們可以根據(jù)需要增長(zhǎng)和縮小。當(dāng)向切片中添加更多元素,且切片容量不足時(shí),Go會(huì)自動(dòng)分配更大的內(nèi)存空間并復(fù)制原有元素到新空間中,從而允許切片繼續(xù)增長(zhǎng)。

  • 引用類型:切片是引用類型,這意味著切片變量存儲(chǔ)的是對(duì)底層數(shù)組的引用(即內(nèi)存地址),而不是數(shù)組的拷貝。因此,通過(guò)不同的切片變量操作同一個(gè)底層數(shù)組的元素時(shí),這些操作會(huì)相互影響。

  • 長(zhǎng)度和容量:切片有兩個(gè)重要的屬性:長(zhǎng)度(length)和容量(capacity)。長(zhǎng)度是切片中元素的數(shù)量;容量是從切片的第一個(gè)元素開始到底層數(shù)組末尾的元素?cái)?shù)量。切片的長(zhǎng)度可以改變,但容量在切片創(chuàng)建時(shí)由底層數(shù)組的大小決定,且一般只能通過(guò)重新切片或使切片指向一個(gè)新的數(shù)組來(lái)改變。

  • 基于數(shù)組:切片是對(duì)數(shù)組的一個(gè)連續(xù)片段的引用,但切片的使用比數(shù)組更加靈活和方便。切片可以動(dòng)態(tài)地增長(zhǎng)和縮小,而數(shù)組的大小在定義時(shí)就確定了,不能改變。

  • 零值:切片的零值是nil,表示切片不引用任何數(shù)組。一個(gè)nil切片的長(zhǎng)度和容量都是0,并且沒(méi)有底層數(shù)組。

  • 切片操作:Go支持對(duì)切片進(jìn)行切片操作,即可以從一個(gè)已存在的切片中再“切”出一個(gè)新的切片。這種操作基于原切片的底層數(shù)組,但可以有不同的長(zhǎng)度和容量。

  • 內(nèi)存連續(xù):切片的底層數(shù)組在內(nèi)存中是連續(xù)的,這使得對(duì)切片中的元素進(jìn)行迭代訪問(wèn)時(shí)效率很高。

  • 內(nèi)置函數(shù)支持:Go的標(biāo)準(zhǔn)庫(kù)提供了許多內(nèi)置函數(shù)來(lái)操作切片,如append用于向切片追加元素,copy用于切片間的元素復(fù)制,以及lencap用于獲取切片的長(zhǎng)度和容量等。

切片數(shù)據(jù)結(jié)構(gòu)

type slice struct {
    // 底層數(shù)組指針(指向一塊連續(xù)內(nèi)存空間的起點(diǎn))
    array unsafe.Pointer
    // 切片長(zhǎng)度
    len   int
    // 切片容量   
    cap   int
}

 cap>=len

切片的創(chuàng)建和初始化

//通過(guò)字面量創(chuàng)建

	/**
	創(chuàng)建字符串切片,長(zhǎng)度和容量都是3
	 */
	slice1 := []string{"aaa","bbb","ccc"}
	fmt.Println(slice1)  //[aaa bbb ccc]

	/**
	創(chuàng)建整形切片,長(zhǎng)度和容量都是4
	 */
	slice2 := []int{10,20,30,40}
	fmt.Println(slice2) //[10 20 30 40]

	//當(dāng)使用切片字面量創(chuàng)建切片時(shí),還可以設(shè)置初始長(zhǎng)度和容量。

	/**
	創(chuàng)建一個(gè)長(zhǎng)度和容量都是100的切片 索引0 = 10,索引99 = 1
	 */
	slice3 := []int{0:10,99:1}
	fmt.Println(slice3) //[10 0 0 ... 1]

	//通過(guò) make() 函數(shù)創(chuàng)建切片


	/**
	創(chuàng)建長(zhǎng)度和容量都是5的切片
	 */
	slice4 := make([]int,5)
	fmt.Println(slice4)  //[0 0 0 0 0] 默認(rèn)對(duì)應(yīng)類型的零值

	/**
	創(chuàng)建長(zhǎng)度=3,容量=5的切片
	 */
	slice5 := make([]string,3,5)
	fmt.Println(slice5)  //[  ]

	/**
	不允許創(chuàng)建容量小于長(zhǎng)度的切片
	 */
	slice6 := make([]int,5,3)
	fmt.Println(slice6)  //invalid argument: length and capacity swapped

切片初始化源碼

func makeslice(et *_type, len, cap int) unsafe.Pointer {

    mem, overflow := math.MulUintptr(et.size, uintptr(cap))
    if overflow || mem > maxAlloc || len < 0 || len > cap {

        mem, overflow := math.MulUintptr(et.size, uintptr(len))
        if overflow || mem > maxAlloc || len < 0 {
            panicmakeslicelen()
        }
        panicmakeslicecap()
    }

    return mallocgc(mem, et, true)
}
  •  math.MulUintptr 方法計(jì)算出初始化切片需要的內(nèi)存和空間大小
  • 空間超限,直接panic
  • mallocgc方法,為切片進(jìn)行空間分配

切片在方法之間的傳遞

func main() {
	sl := []int{1,2,3,4,5}
	fmt.Println(sl)  //[1 2 3 4 5]
	change(sl)
	fmt.Println(sl)  //[10 2 3 4 5]
}
func change(sl []int) {
	sl[0] = 10
}

每次在方法之間傳遞切片時(shí),會(huì)將切片實(shí)例本身進(jìn)行一次值拷貝(也可以叫淺拷貝),會(huì)將array指針,len長(zhǎng)度,cap容量進(jìn)行拷貝所以方法中和方法外的切邊array指向同一片內(nèi)存空間,因此在局部方法中執(zhí)行修改操作時(shí),還會(huì)根據(jù)這個(gè)地址信息影響到原 slice 所屬的內(nèi)存空間,從而對(duì)內(nèi)容發(fā)生影響;

但是如果在函數(shù)中的切片發(fā)生了擴(kuò)容,此時(shí)內(nèi)外就是兩個(gè)獨(dú)立的切片;

截取切片

在Go語(yǔ)言中,可以通過(guò)指定起始索引和結(jié)束索引來(lái)截取一個(gè)新的切片(包前不包后);

slice[start:end]
//slice要截取的原始切片
//start截取切片的開始位置,不填默認(rèn)為0
//end截取切片的結(jié)束位置,不填默認(rèn)為切片長(zhǎng)度
s := []int{1, 2, 3, 4, 5}
	// 截取整個(gè)切片
	subS1 := s[:]
	fmt.Println(subS1) // 輸出: [1 2 3 4 5]

	// 截取索引1到4(不包含4)的元素
	subS2 := s[1:4]
	fmt.Println(subS2) // 輸出: [2 3 4]

	// 從索引0開始截取到索引4(不包含4)
	subS3 := s[:4]
	fmt.Println(subS3) // 輸出: [1 2 3 4]

	// 從索引2開始截取到切片末尾
	subS4 := s[2:]
	fmt.Println(subS4) // 輸出: [3 4 5]

截取出的切片和原始切片的關(guān)系

在對(duì)切片 slice 執(zhí)行截取操作時(shí),本質(zhì)上是一次引用傳遞操作,因?yàn)椴徽撊绾谓厝?,底層?fù)用的都是同一塊內(nèi)存空間中的數(shù)據(jù),只不過(guò),截取動(dòng)作會(huì)創(chuàng)建出一個(gè)新的 slice header 實(shí)例;

 s := []int{2,3,4,5}
  s1 := s[1:]

往切片中新增元素(append)

通過(guò)append方法可以實(shí)現(xiàn)在切片的末尾添加元素

func main() {  
    s := []int{1, 2, 3}  
    // 使用 append 函數(shù)在切片末尾添加元素 4  
    s = append(s, 4)  
    fmt.Println(s) // 輸出: [1 2 3 4]  
}

func main() {  
    s := []int{1, 2, 3}  
    // 使用 append 函數(shù)在切片末尾添加多個(gè)元素  
    s = append(s, 4, 5, 6)  
    fmt.Println(s) // 輸出: [1 2 3 4 5 6]  
}

func main() {  
    s1 := []int{1, 2, 3}  
    s2 := []int{4, 5, 6}  
    // 使用 append 函數(shù)將 s2 添加到 s1 的末尾  
    s1 = append(s1, s2...) // 注意 s2 后的 ... 用于將 s2 展開為元素序列  
    fmt.Println(s1) // 輸出: [1 2 3 4 5 6]  
}

func main() {  
    s := []int{1, 3, 4, 5}  
    // 在索引 1 的位置插入元素 2  
    // 首先,將索引 1 及其之后的元素向后移動(dòng)一位  
    s = append(s[:1], append([]int{2}, s[1:]...)...)  
    fmt.Println(s) // 輸出: [1 2 3 4 5]  
}

刪除切片中的元素

在Go語(yǔ)言中,切片(slice)本身并不提供直接的刪除元素的方法,因?yàn)榍衅菍?duì)底層數(shù)組的抽象,而數(shù)組的大小是固定的。但是,通過(guò)以下幾種方式來(lái)實(shí)現(xiàn)“刪除”切片中的元素;

//使用切片操作刪除元素(適用于刪除末尾元素)
s := []int{1, 2, 3, 4, 5}  
// 刪除切片末尾的元素  
s = s[:len(s)-1]  
fmt.Println(s) // 輸出: [1 2 3 4]


//使用append和切片操作刪除任意位置的元素
s := []int{1, 2, 3, 4, 5}  
// 假設(shè)我們要?jiǎng)h除索引為2的元素(值為3)  
index := 2  
// 將index之后的元素(不包括index)復(fù)制到前面,然后截?cái)嗲衅? 
s = append(s[:index], s[index+1:]...)  
fmt.Println(s) // 輸出: [1 2 4 5]

//使用循環(huán)和條件語(yǔ)句刪除滿足條件的元素
s := []int{1, 2, 3, 4, 5}  
// 刪除所有值為3的元素  
var newS []int  
for _, value := range s {  
    if value != 3 {  
        newS = append(newS, value)  
    }  
}  
s = newS  
fmt.Println(s) // 輸出: [1 2 4 5]

拷貝切片

slice 的拷貝可以分為簡(jiǎn)單拷貝和完整拷貝兩種類型;

要實(shí)現(xiàn)簡(jiǎn)單拷貝(淺拷貝),我們只需要對(duì)切片的字面量進(jìn)行賦值傳遞即可,這樣相當(dāng)于創(chuàng)建出了一個(gè)新的 slice header 實(shí)例,但是其中的指針 array、容量 cap 和長(zhǎng)度 len 仍和老的 slice header 實(shí)例相同;

slice 的完整復(fù)制(深拷貝),指的是會(huì)創(chuàng)建出一個(gè)和 slice 容量大小相等的獨(dú)立的內(nèi)存區(qū)域,并將原 slice 中的元素一一拷貝到新空間中,在實(shí)現(xiàn)上,slice 的完整復(fù)制可以調(diào)用系統(tǒng)方法 copy;

s := []int{1, 2, 3}  
// 分配一個(gè)新的切片,長(zhǎng)度和容量與s相同  
sCopy := make([]int, len(s))  
// 使用copy函數(shù)復(fù)制元素  
copy(sCopy, s)  
  
// 現(xiàn)在sCopy是s的一個(gè)獨(dú)立拷貝  
fmt.Println(sCopy) // 輸出: [1 2 3]

切片的擴(kuò)容

什么時(shí)候會(huì)觸發(fā)擴(kuò)容

當(dāng) slice 當(dāng)前的長(zhǎng)度 len 與容量 cap 相等時(shí),下一次 append 操作就會(huì)引發(fā)一次切片擴(kuò)容;

擴(kuò)容步驟

1.計(jì)算目標(biāo)容量
case1:如果新切片的長(zhǎng)度>舊切片容量的兩倍,則新切片容量就為新切片的長(zhǎng)度case2:

  • 如果舊切片的容量小于256,那么新切片的容量就是舊切片的容量的兩倍
  • 反之需要用舊切片容量按照1.25倍的增速,直到>=新切片長(zhǎng)度,為了更平滑的過(guò)渡,每次擴(kuò)大1.25倍,還會(huì)加上3/4* 256

2.進(jìn)行內(nèi)存對(duì)齊
需要按照Go內(nèi)存管理的級(jí)別去對(duì)齊內(nèi)存,最終容量以這個(gè)為準(zhǔn)

到此這篇關(guān)于Golang動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Golang動(dòng)態(tài)數(shù)組內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并發(fā)聊天室的項(xiàng)目實(shí)戰(zhàn)

    Go語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并發(fā)聊天室的項(xiàng)目實(shí)戰(zhàn)

    本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的并發(fā)聊天室的項(xiàng)目實(shí)戰(zhàn),文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn)

    Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn)

    go語(yǔ)言用來(lái)執(zhí)行一個(gè)系統(tǒng)的命令相對(duì)python來(lái)說(shuō)還是有點(diǎn)復(fù)雜的,執(zhí)行命令是一個(gè)非常常見的需求,本文主要介紹了Go語(yǔ)言執(zhí)行cmd命令庫(kù)的方法實(shí)現(xiàn),感興趣的可以了解一下
    2023-09-09
  • 詳解Go?依賴管理?go?mod?tidy

    詳解Go?依賴管理?go?mod?tidy

    這篇文章主要為大家介紹了詳解Go?依賴管理?go?mod?tidy,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 一文帶你了解Golang中select的實(shí)現(xiàn)原理

    一文帶你了解Golang中select的實(shí)現(xiàn)原理

    select是go提供的一種跟并發(fā)相關(guān)的語(yǔ)法,非常有用。本文將介紹?Go?語(yǔ)言中的?select?的實(shí)現(xiàn)原理,包括?select?的結(jié)構(gòu)和常見問(wèn)題、編譯期間的多種優(yōu)化以及運(yùn)行時(shí)的執(zhí)行過(guò)程
    2023-02-02
  • 從源碼深入理解golang?RWMutex讀寫鎖操作

    從源碼深入理解golang?RWMutex讀寫鎖操作

    這篇文章主要介紹了從源碼深入理解golang?RWMutex讀寫鎖操作,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • golang 實(shí)現(xiàn)一個(gè)負(fù)載均衡案例(隨機(jī),輪訓(xùn))

    golang 實(shí)現(xiàn)一個(gè)負(fù)載均衡案例(隨機(jī),輪訓(xùn))

    這篇文章主要介紹了golang 實(shí)現(xiàn)一個(gè)負(fù)載均衡案例(隨機(jī)、輪訓(xùn)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Go語(yǔ)言中樂(lè)觀鎖與悲觀鎖的具體使用

    Go語(yǔ)言中樂(lè)觀鎖與悲觀鎖的具體使用

    樂(lè)觀鎖和悲觀鎖是兩種思想,用于解決并發(fā)場(chǎng)景下的數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題,本文主要介紹了Go語(yǔ)言中樂(lè)觀鎖與悲觀鎖的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • goland遠(yuǎn)程調(diào)試k8s上容器的實(shí)現(xiàn)

    goland遠(yuǎn)程調(diào)試k8s上容器的實(shí)現(xiàn)

    本文主要介紹了goland遠(yuǎn)程調(diào)試k8s上容器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • golang gin 監(jiān)聽rabbitmq隊(duì)列無(wú)限消費(fèi)的案例代碼

    golang gin 監(jiān)聽rabbitmq隊(duì)列無(wú)限消費(fèi)的案例代碼

    這篇文章主要介紹了golang gin 監(jiān)聽rabbitmq隊(duì)列無(wú)限消費(fèi),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • Go語(yǔ)言中sync.Mutex的使用方法

    Go語(yǔ)言中sync.Mutex的使用方法

    本文主要介紹了golang中sync.Mutex的實(shí)現(xiàn)方法,mutex主要有兩個(gè) method:Lock()和Unlock(),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03

最新評(píng)論