Go 語言中的動態陣列:深入解析切片

更新於 發佈於 閱讀時間約 9 分鐘


raw-image

👨‍💻簡介

在 Go 語言中,切片(Slice)是一種動態序列的資料結構,能夠方便地存儲和操作多個相同類型的元素。切片相比於陣列,更具有彈性,因為它的大小是可變的,可以根據需要動態增長或縮小。切片在處理集合型資料時非常實用,讓你能夠輕鬆地新增、刪除、修改和操作元素,同時避免了固定大小的限制。

切片的基本概念

切片是由一個指向陣列的指針、切片長度和切片容量組成的。切片的長度指的是切片中實際包含的元素個數,而切片的容量則是從切片開始的底層陣列中能夠訪問的元素個數。切片的容量可以大於或等於切片的長度。

宣告和初始化切片

在 Go 中,宣告和初始化切片可以使用以下的語法:

var slice1 []int                     // 創建一個整數切片,大小和容量都是 0
slice2 := []string{"A", "B", "C"} // 創建一個包含三個字串元素的切片
slice3 := make([]int, 5) // 創建一個整數切片,大小為 5,容量也為 5
slice4 := make([]int, 3, 5) // 創建一個整數切片,大小為 3,容量為 5

切片的基本操作

新增元素到切片

Go語言中有個內件函式append(),可以用來新增元素到切片中,這使得切片能夠根據需求動態增長。

numbers := []int{10, 20, 30}
numbers = append(numbers, 40, 50) // 新增兩個元素到切片

需要注意的是,如果切片的容量不足以容納新增的元素,append() 函式會創建一個新的切片,並將舊的元素和新的元素一同複製到新的切片中。

查詢和修改切片元素

切片的元素可以通過索引來存取,索引從 0 開始計數。

numbers := []int{10, 20, 30, 40, 50}
firstNumber := numbers[0] // 存取第一個元素,值為 10
secondNumber := numbers[1] // 存取第二個元素,值為 20
numbers[2] = 35 // 修改切片中的元素,將第三個元素改為 35

切割和遍歷切片

可以使用切片的切割操作來獲取部分切片,這可以通過指定切片的起始索引和結束索引來實現:

numbers := []int{10, 20, 30, 40, 50}
subSlice := numbers[1:4] // 從第二個元素到第四個元素的子切片,值為 [20 30 40]
  • [:]:使用 [:] 語法可以獲得完整的切片,即包含所有元素的切片。
  • [x:]:這種語法表示從索引 x 開始,提取所有直到切片結尾的元素。
  • [:x]:這種語法表示提取從開頭到索引 x-1 的元素,不包含索引 x 的元素。

切片的遍歷可以使用傳統的索引方式,或者使用 range 來簡化遍歷過程。

numbers := []int{10, 20, 30, 40, 50}

// 使用傳統的索引方式遍歷切片
for i := 0; i < len(numbers); i++ {
fmt.Println(numbers[i])
}
// 使用 range 遍歷切片
for index, value := range numbers {
fmt.Printf("索引:%d,值:%d\n", index, value)
}
for i := range numbers {
fmt.Println(numbers[i])
}

刪除切片元素

雖然切片沒有內建的刪除方法,不過可以使用切片的切割操作,將不需要的元素排除在外。

slice := []int{10, 20, 30, 40, 50}
indexToDelete := 2
slice = append(slice[:indexToDelete], slice[indexToDelete+1:]...) // 刪除索引 2 的元素

切片的容量

切片的容量就是指,你從切片開始的位置能夠往後訪問到的元素數量。當你在切片上進行新增元素的操作時,如果新加進來的元素數量超過了切片目前的容量,Go 語言會做一些事情:它會重新搞一個更大的陣列,然後把舊的元素都複製到這個新陣列中。這個過程會花一些時間,也就是所謂的性能開銷。

package main

import "fmt"
func main() {
numbers := []int{1, 2, 3}
fmt.Println("長度:", len(numbers)) // 輸出:長度:3
fmt.Println("容量:", cap(numbers)) // 輸出:容量:3
slice := numbers[1:2]
fmt.Println("切片:", slice) // 輸出:切片:[2]
fmt.Println("切片長度:", len(slice)) // 輸出:切片長度:1
fmt.Println("切片容量:", cap(slice)) // 輸出:切片容量:2
// 切片的容量是從切片的起始索引開始計算,一直到底層陣列的末尾索引。因此容量為2
// 新增元素超過切片容量時,會自動擴容並分配更大的底層陣列
slice = append(numbers, 4) // 新切片為 [1, 2, 3, 4]
fmt.Println("切片:", slice) // 輸出:切片:[1 2 3 4]
fmt.Println("切片長度:", len(slice)) // 輸出:切片長度:4
fmt.Println("切片容量:", cap(slice)) // 輸出:切片容量:6
}

切片的特性、限制與使用場景

切片的特性

  • 切片的大小是動態的,可以隨時進行增長或縮小。
  • 切片可以方便地從現有的陣列或切片中創建,不需要顯式地指定容量。
  • 切片的新增、刪除、修改操作都非常方便,讓你能夠輕鬆地操作集合型資料。
  • 切片的背後通常使用動態陣列來實現,因此在內存佈局上更具彈性,不受固定大小的限制。
  • 切片是引用類型,這意味著它們引用底層的陣列,而不是複製數據。當你將一個切片賦值給另一個切片,它們實際上共享同一份數據。因此,對其中一個切片所做的修改將影響到另一個切片。 以下是一個實際案例:
slice1 := []int{1, 2, 3}
slice2 := slice1
slice2[0] = 3
fmt.Println(slice1, slice2) // 輸出:[3 2 3] [3 2 3]

在這裡,修改 slice2 的值同樣影響了 slice1,因為它們引用同一份底層數據。這是切片和陣列之間的一個重要區別。

切片的限制

  • 記憶體配置: 切片的內部實現中使用了底層的陣列,因此切片所佔用的記憶體空間可能比實際所需大。當切片的元素數量增加時,Go 語言可能會重新配置更大的陣列,導致一些性能開銷。
  • 不適用於大型資料: 對於大型資料集合,切片可能不是最佳選擇。大型切片可能導致記憶體占用過多,影響程式的效能。
  • 不支援多維切片: 切片僅支援一維結構,如果需要處理多維資料,可能需要自行實現多維切片的概念。

使用場景

  • 動態資料集合: 切片的大小是可變的,使其非常適用於處理動態資料集合,無需事先知道集合的大小。
  • API 請求和回應: 在處理 API 請求和回應時,切片可用於儲存和解析不確定數量的請求參數或回應資料。
  • 資料過濾和轉換: 使用 range 遍歷切片,可以輕鬆地過濾或轉換切片中的元素,進行處理和計算。
  • 傳遞函式參數: 切片的引用類型特性使其適用於傳遞函式參數,避免不必要的資料複製。
  • 檔案讀寫: 切片可用於讀取大量數據,進行處理後再寫回檔案。
  • 實現堆疊和佇列: 使用切片可以實現簡單的堆疊(後進先出)和佇列(先進先出)結構。
  • 排序和搜尋: 切片在排序和搜尋資料時非常有用,可以利用 sort 套件進行排序,並使用二分搜尋等技術進行搜尋。

常見用法

  • 資料過濾和轉換
// 將切片中的所有元素乘以 2
numbers := []int{1, 2, 3, 4, 5}
for i := range numbers {
numbers[i] *= 2
}

// 過濾出大於 3 的元素
filteredNumbers := []int{}
for _, num := range numbers {
if num > 3 {
filteredNumbers = append(filteredNumbers, num)
}
}
  • 傳遞函式參數
func modifySlice(slice []int) {
slice[0] = 100
}

numbers := []int{1, 2, 3}
modifySlice(numbers)

小結

切片是 Go 語言中非常實用的資料結構,它解決了陣列大小固定的限制,讓你能夠輕鬆地處理動態大小的集合型資料。切片的操作包括取得、修改、新增、刪除等,讓你可以靈活地處理資料集合。

在遍歷切片時,range 很方便地提供了索引和值,讓你能夠輕鬆地訪問切片中的元素。切片的特性和優勢使得它在處理動態數據集合時成為 Go 程式設計中的一個重要工具。

📚Reference

留言
avatar-img
留言分享你的想法!
avatar-img
Alan的開發者天地
19會員
83內容數
golang
Alan的開發者天地的其他內容
2023/10/04
👨‍💻 簡介 最近想要透過小實作來撰寫筆記,達到做中學的效果,因此就來實作個小爬蟲順便結合前面學到的package做一個小複習。
Thumbnail
2023/10/04
👨‍💻 簡介 最近想要透過小實作來撰寫筆記,達到做中學的效果,因此就來實作個小爬蟲順便結合前面學到的package做一個小複習。
Thumbnail
2023/09/28
👨‍💻簡介 今天來介紹一個自己開發後端蠻常用的一個 package,promptui,拿來做menu真的很方便,promptui有兩個主要的輸入模式: Prompt:跳出單行使用者輸入。 Select:提供一個選項列表供使用者選擇。
Thumbnail
2023/09/28
👨‍💻簡介 今天來介紹一個自己開發後端蠻常用的一個 package,promptui,拿來做menu真的很方便,promptui有兩個主要的輸入模式: Prompt:跳出單行使用者輸入。 Select:提供一個選項列表供使用者選擇。
Thumbnail
2023/09/26
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
2023/09/26
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
看更多
你可能也想看
Thumbnail
常常被朋友問「哪裡買的?」嗎?透過蝦皮分潤計畫,把日常購物的分享多加一個步驟,就能轉換成現金回饋。門檻低、申請簡單,特別適合學生與上班族,讓零碎時間也能創造小確幸。
Thumbnail
常常被朋友問「哪裡買的?」嗎?透過蝦皮分潤計畫,把日常購物的分享多加一個步驟,就能轉換成現金回饋。門檻低、申請簡單,特別適合學生與上班族,讓零碎時間也能創造小確幸。
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
複習一下: 我們學習了關於撰寫程式的相關觀念 條件分支(if/else) : 藉由條件分支讓程式執行相對應的功能。 迴圈(while loop ) :程式利用迴圈反覆執行某個區塊的程式碼。 字串處理 (string) : 每個程式都在處理資料,而字串是一種非常重要且常用的資料。 函式(fu
Thumbnail
複習一下: 我們學習了關於撰寫程式的相關觀念 條件分支(if/else) : 藉由條件分支讓程式執行相對應的功能。 迴圈(while loop ) :程式利用迴圈反覆執行某個區塊的程式碼。 字串處理 (string) : 每個程式都在處理資料,而字串是一種非常重要且常用的資料。 函式(fu
Thumbnail
JavaScript Array 基本操作筆記
Thumbnail
JavaScript Array 基本操作筆記
Thumbnail
你還記得那次與朋友一起的燒烤派對,大家輪流挑選食材放到烤架上烤嗎?這就好比使用迭代器模式 (Iterator Pattern) 來遍歷集合!讓我們一起來看看它是如何工作的,以及為什麼它如此有用。
Thumbnail
你還記得那次與朋友一起的燒烤派對,大家輪流挑選食材放到烤架上烤嗎?這就好比使用迭代器模式 (Iterator Pattern) 來遍歷集合!讓我們一起來看看它是如何工作的,以及為什麼它如此有用。
Thumbnail
👨‍💻簡介 在 Go 語言中,切片(Slice)是一種動態序列的資料結構,能夠方便地存儲和操作多個相同類型的元素。切片相比於陣列,更具有彈性,因為它的大小是可變的,可以根據需要動態增長或縮小。切片在處理集合型資料時非常實用,讓你能夠輕鬆地新增、刪除、修改和操作元素。
Thumbnail
👨‍💻簡介 在 Go 語言中,切片(Slice)是一種動態序列的資料結構,能夠方便地存儲和操作多個相同類型的元素。切片相比於陣列,更具有彈性,因為它的大小是可變的,可以根據需要動態增長或縮小。切片在處理集合型資料時非常實用,讓你能夠輕鬆地新增、刪除、修改和操作元素。
Thumbnail
👨‍💻簡介 陣列就像是一個儲存相同類型資料的容器,你可以想像成裝滿了一樣東西的盒子,每個東西都叫做陣列元素。這種類型可以是基本的,像是整數或字串,也可以是你自己定義的型別。不過陣列有個限制,就是大小一旦確定就無法改變。在Go語言裡,陣列的長度也是型別的一部分。
Thumbnail
👨‍💻簡介 陣列就像是一個儲存相同類型資料的容器,你可以想像成裝滿了一樣東西的盒子,每個東西都叫做陣列元素。這種類型可以是基本的,像是整數或字串,也可以是你自己定義的型別。不過陣列有個限制,就是大小一旦確定就無法改變。在Go語言裡,陣列的長度也是型別的一部分。
Thumbnail
精通 Golang 正則表達式的代碼優化。透過高效的字符串處理、動態模式生成和編譯,以及處理複雜文本匹配,將正則表達式融入你的代碼中,提升效能。
Thumbnail
精通 Golang 正則表達式的代碼優化。透過高效的字符串處理、動態模式生成和編譯,以及處理複雜文本匹配,將正則表達式融入你的代碼中,提升效能。
Thumbnail
Hi,大家好。我是茶桁。 之前两节分别介绍了字符串和列表,今天,我们来讲讲另外一个常用到的数据类型:元组。 元组和列表很像,两者都是一组有序的数据的组合。但是也有很多不同点,比如元组内的元素一旦定义了就不可以再修改,因此元组称为不可变数据类型。 元组定义 元组的定义方式包括以下要点: 定义
Thumbnail
Hi,大家好。我是茶桁。 之前两节分别介绍了字符串和列表,今天,我们来讲讲另外一个常用到的数据类型:元组。 元组和列表很像,两者都是一组有序的数据的组合。但是也有很多不同点,比如元组内的元素一旦定义了就不可以再修改,因此元组称为不可变数据类型。 元组定义 元组的定义方式包括以下要点: 定义
Thumbnail
我們介紹了字串和列表的索引和切片操作。索引使用方括號[]來選擇字串或列表中的特定元素,並可以使用正向索引(從0開始)或反向索引(從最後一個元素為-1)來訪問元素。切片使用方括號[]和冒號:來選擇字串或列表中的一段子序列,指定起始位置和結束位置(不包含),並可以使用步長來控制間隔。
Thumbnail
我們介紹了字串和列表的索引和切片操作。索引使用方括號[]來選擇字串或列表中的特定元素,並可以使用正向索引(從0開始)或反向索引(從最後一個元素為-1)來訪問元素。切片使用方括號[]和冒號:來選擇字串或列表中的一段子序列,指定起始位置和結束位置(不包含),並可以使用步長來控制間隔。
Thumbnail
今天來到了第9天的教學,我們繼續來進行Numpy的教學,今天主要教的內容為陣列索引、重塑(reshape),以及調整大小等操作,那我們就開始吧!!
Thumbnail
今天來到了第9天的教學,我們繼續來進行Numpy的教學,今天主要教的內容為陣列索引、重塑(reshape),以及調整大小等操作,那我們就開始吧!!
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News