1. 程式人生 > >golang學習筆記 ---陣列與切片

golang學習筆記 ---陣列與切片

陣列:

  • golang陣列包含的每個資料稱為陣列元素(element),陣列包含的元素個數被稱為陣列長度(length)。
  • golang陣列的長度在定義後不可更改,並且在宣告時可以是一個常量或常量表達式(在編譯期即可計算結果的表示式)。golang陣列長度是一個內建常量,可以用len()函式來獲取。
  •  golang陣列是一個值型別,在賦值和作為引數傳遞時都將產生一次複製動作,因此在函式體中無法修改傳入的陣列的內容

陣列宣告和初始化

▶ 陣列宣告

▪ 語法如下

var array [n]Type

// 陣列宣告和初始化
var array [n]Type = [n]Type{v1, v2, ..., vn}
var array = [n]Type{v1, v2, ..., vn}
array := [n]Type{v1, v2, ..., vn}

▪ 示例如下

[32]byte                    // 長度為32的陣列,每個元素為一個位元組
[2*N] struct { x, y int32 } // 複雜型別陣列
[1000]*float64              // 指標陣列
[3][5]int                   // 二維陣列
[2][2][2]float64            // 等同於[2]([2]([2]float64))

• 陣列常用操作

▶ 遍歷元素

⊙ 按下標遍歷

        使用len()獲取元素個數,然後按下標進行元素遍歷操作。

▪ 語法如下
for i := 0; i < len(array); i++ {
    ...
}
▪ 示例如下
package main
import "fmt"
func main() {
	array := [5]int{1, 2, 3, 4, 5}
	for i := 0; i < len(array); i++ {
		fmt.Println("array[", i, "] =", array[i])
	}
}
⊙ rang遍歷

        可以使用range關鍵字來快速遍歷所有元素。

▪ 語法如下
for i, v := range array {
    ...
}
▪ 示例如下
package main
import "fmt"
func main() {
	array := [5]int{1, 2, 3, 4, 5}
	for i, v := range array {
		fmt.Println("array[", i, "] =", v)
	}
}

陣列切片

        golang陣列切片解決的問題:golang陣列長度在定義之後無法再次修改,並且陣列是值型別,每次傳遞都將產生一份副本。

        golang陣列切片擁有獨立的資料結構,可抽象為3個變數:一個指向原陣列的指標陣列切片中元素個數陣列切片分配的儲存空間

• 建立陣列切片

基於陣列

▪ 語法如下

var arraySlice []Type = array[first:last]

        陣列切片的元素範圍為[first, last)

        first和last的值可以省略,預設情況下,first=0,last=len(array)

        first和last的值必須滿足條件:非負,0 ≤ first ≤ last ≤ len(array),否則編譯器將給出錯誤:
       

       

       

▪ 示例如下

package main
import "fmt"
func main() {
	var array [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var arraySlice1 []int = array[:]   // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
	var arraySlice2 []int = array[:5]  // 1, 2, 3, 4, 5
	var arraySlice3 []int = array[5:]  // 6, 7, 8, 9, 10
	var arraySlice4 []int = array[3:8] // 4, 5, 6, 7, 8
	fmt.Println("\nElements of arraySlice1: ")
	for _, v := range arraySlice1 {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of arraySlice2: ")
	for _, v := range arraySlice2 {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of arraySlice3: ")
	for _, v := range arraySlice3 {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of arraySlice4: ")
	for _, v := range arraySlice4 {
		fmt.Print(v, " ")
	}
	fmt.Println()
}

直接建立

        golang提供的內建函式make()可以用於靈活地建立陣列切片。

▪ 語法如下

// 建立一個初始元素個數為m的陣列切片
arraySlice := make([]Type, m)

// 建立一個初始元素個數為m的陣列切片,並預留n個元素的儲存空間
arraySlice := make([]Type, m, n)

// 直接建立並初始化包含m個元素的陣列切片
arraySlice := []Type{v1, v2, ..., vn}

▪ 示例如下

  package main
import "fmt"
func main() {
	arraySlice1 := make([]int, 5)       // 0 0 0 0 0
	arraySlice2 := make([]int, 5, 10)   // 0 0 0 0 0
	arraySlice3 := []int{1, 2, 3, 4, 5} // 1 2 3 4 5
	fmt.Println("\nElements of arraySlice1: ")
	for _, v := range arraySlice1 {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of arraySlice2: ")
	for _, v := range arraySlice2 {
		fmt.Print(v, " ")
	}
	fmt.Println("\nElements of arraySlice3: ")
	for _, v := range arraySlice3 {
		fmt.Print(v, " ")
	}
}

基於陣列切片

        陣列切片(newSlice)也可以基於另一個數組切片(oldSlice)建立。

        newSlice元素範圍可以超過oldSlice所包含的元素個數,只要選擇範圍不超過oldSlice的儲存能力,即cap(oldSlice)的值,那麼這個建立是合法的,newSlice中超出oldSlice元素的部分都會填上0。

        newSlice的儲存能力等同於oldSlice的儲存能力,即cap(newSlice) = cap(oldSlice)

▪ 語法如下

newSlice := oldSlice[first:last] // 0 ≤ first ≤ last ≤ cap(oldSlice)

▪ 示例如下

package main
import "fmt"
func main() {
	oldSlice := make([]int, 5, 10)
	newSlice := oldSlice[:8]
	fmt.Println("Length   of oldSlice: ", len(oldSlice)) // 5
	fmt.Println("Capacity of oldSlice: ", cap(oldSlice)) // 10
	fmt.Println("Length   of newSlice: ", len(newSlice)) // 8
	fmt.Println("Capacity of newSlice: ", cap(newSlice)) // 10
}

• 陣列切片的元素個數和儲存能力

        與陣列相比,陣列切片多了一個儲存能力(capacity)的概念,即當前容納的元素個數和分配的空間可以是兩個不同的值。

        儲存能力,可以理解為最大容納元素個數,最大容納元素個數減去當前容納元素個數剩下的空間是隱藏的,不能直接使用。如果要往隱藏空間中新增元素,可以使用append()函式。

        取得當前容納元素個數可以使用len()函式,取得最大容納元素個數可以使用cap()函式

package main
import "fmt"
func main() {
	arraySlice := make([]int, 5, 10)
	fmt.Println("len(arraySlice):", len(arraySlice)) // len(arraySlice): 5
	fmt.Println("cap(arraySlice):", cap(arraySlice)) // cap(arraySlice): 10
}

• 陣列切片常用操作

▶ 遍歷元素

⊙ 按下標遍歷

        與遍歷陣列一樣,使用len()獲取元素個數,然後按下標進行元素遍歷操作。

▪ 語法如下
for i := 0; i < len(arraySlice); i++ {
    ...
}
▪ 示例如下
package main
import "fmt"
func main() {
	arraySlice := []int{1, 2, 3, 4, 5}
	for i := 0; i < len(arraySlice); i++ {
		fmt.Println("arraySlice[", i, "] =", arraySlice[i])
	}
}

⊙ rang遍歷

        與遍歷陣列一樣,可以使用range關鍵字來快速遍歷所有元素。

▪ 語法如下
for i, v := range arraySlice {
    ...
}
▪ 示例如下
package main
import "fmt"
func main() {
	arraySlice := []int{1, 2, 3, 4, 5}
	for i, v := range arraySlice {
		fmt.Println("arraySlice[", i, "] =", v)
	}
}

▶ 增加元素

        為陣列切片增加元素的方法是使用append()函式。

⊙ 追加元素

        追加元素時,會自動處理儲存空間不足的問題,如果追加的內容超過當前最大容納元素空間,那麼陣列切片會自動分配一塊足夠大的記憶體。自動分配記憶體策略為:當前儲存能力 * 2,即cap(arraySlice) * 2

▪ 語法如下
arraySlice = append(arraySlice, v1, v2, ..., vn)
▪ 示例如下
package main
import "fmt"
func main() {
	arraySlice := make([]int, 0, 10)
	arraySlice = append(arraySlice, 1, 2, 3, 4, 5)
	fmt.Println("len(arraySlice) =", len(arraySlice)) // 5
	fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 10
	for _, v := range arraySlice {
		fmt.Print(v, " ")
	}
	fmt.Println()
	arraySlice = append(arraySlice, 6, 7, 8, 9, 10, 11, 12, 13)
	fmt.Println("len(arraySlice) =", len(arraySlice)) // 13
	fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 20
	for _, v := range arraySlice {
		fmt.Print(v, " ")
	}
}

追加陣列切片

       為陣列切片arraySlice1追加陣列切片arraySlice2時,注意在arraySlice2後面追加三個點,這三個點的意思是把arraySlice2所有元素打散後傳遞給append()函式,這是由於append()函式從第二個引數起的所有引數都必須是待附加的單個元素。

▪ 語法如下
arraySlice = append(arraySlice, appendSlice...)
▪ 示例如下
package main
import "fmt"
func main() {
	arraySlice := []int{1, 2, 3}
	appendSlice := []int{4, 5}
	arraySlice = append(arraySlice, appendSlice...)
	fmt.Println("len(arraySlice) =", len(arraySlice)) // 5
	fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 6
	for _, v := range arraySlice {
		fmt.Print(v, " ")
	}
}

▶ 刪除元素

       陣列切片可以動態新增元素,但沒有刪除元素的函式。代替方法是:可以使用陣列切片重新組合的方式來刪除一個或多個項。不過從陣列切片這種資料結構來看,本身並不適合做刪除操作,所以儘量減少使用。

▪ 示例如下

package main
import "fmt"
func main() {
	s := []int{1, 2, 3, 4, 5, 6}
	i := 2
	s = append(s[:i], s[i+1:]...)
	fmt.Println(s) // [1 2 4 5 6]
}

▶ 切片之間元素複製

        golang使用內建函式copy()將陣列切片arraySlice2的內容複製到陣列切片arraySlice1中。

        如果兩個陣列切片元素個數不同,那麼就會按其中元素個數較少的陣列切片元素個數進行復制操作。

▪ 示例如下

package main
import "fmt"
func main() {
	arraySlice1 := []int{1, 2, 3, 4, 5}
	arraySlice2 := []int{5, 4, 3}
	copy(arraySlice2, arraySlice1) // 只會複製arraySlice1的前3個元素到arraySlice2中
	fmt.Println(arraySlice2)       // [1 2 3]
	arraySlice3 := []int{1, 2, 3, 4, 5}
	arraySlice4 := []int{5, 4, 3}
	copy(arraySlice3, arraySlice4) // 只會複製arraySlice4的3個元素到arraySlice3的前3個位置
	fmt.Println(arraySlice3)       // [5 4 3 4 5]
}

相關推薦

golang學習筆記 ---陣列切片

陣列: golang陣列包含的每個資料稱為陣列元素(element),陣列包含的元素個數被稱為陣列長度(length)。 golang陣列的長度在定義後不可更改,並且在宣告時可以是一個常量或常量表達式(在編譯期即可計算結果的表示式)。golang陣列長度是一個內建常量,可以用len()函式來獲取。  gol

go語言學習筆記--陣列切片

一、陣列 基本概念 1、一組相同型別已編號且長度固定的資料項序列 宣告格式:var identifier [len]type 2、Go語言中陣列是一種值型別,不是c中指向首元素地址,函式中使用 陣列作為引數,是值傳遞,會產生一次陣列拷貝。不會修改原資料 3、將陣列傳

golang學習筆記 ---數組切片

info lds 位置 內存 print city func 超過 src 數組: golang數組包含的每個數據稱為數組元素(element),數組包含的元素個數被稱為數組長度(length)。 golang數組的長度在定義後不可更改,並且在聲明時可以是一個常量或常量表

深入學習golang(1)—陣列切片

資料(array)與切片(slice) 陣列宣告: ArrayType   = "[" ArrayLength "]" ElementType . 例如: var a [32] int var b [3][5] int 在Go和C中,陣列的工作方式有幾個重要的差別。在Go中, (1)陣列是值型別。將一個數組

[Golang學習筆記] 07 陣列切片

01-06回顧: Go語言開發環境配置, 常用原始碼檔案寫法, 程式實體(尤其是變數)及其相關各種概念和程式設計技巧:   型別推斷,變數重宣告,可重名變數,型別推斷,型別轉換,別名型別和潛在型別 陣列: 陣列型別的值的長度是固定的,在宣告陣列的時候,長度必須給定,並且在之後不

資料結構演算法之美專欄學習筆記-陣列

什麼是陣列 陣列(Array)是一種線性表資料結構。它用一組連續的記憶體空間,來儲存一組具有相同型別的資料。 線性表 線性表就是資料排成像一條線一樣的結構。 常見的線性表結構:陣列,連結串列、佇列、棧等。 非線性表有:二叉樹、圖、堆等。 連續的記憶體空間和相同型別的資料 優點:兩限制使得

Go學習筆記陣列切片和容器(五)

func main() { //定義陣列 數量在型別的前面 var arr [5] int // 不定義值為0 arr1 := [3]int{1} // := 必須賦值 最少賦值1位 arr2 := [...]int{4,5,6,7,8} //...可不規定長度 //二維陣列 var

golang 學習筆記 ---記憶體分配管理

Go語言——記憶體管理 參考: 圖解 TCMalloc Golang 記憶體管理 Go 記憶體管理 問題 記憶體碎片:避免記憶體碎片,提高記憶體利用率。 多執行緒:穩定性,效率問題。 記憶體分配   記憶

golang學習筆記之引用型別值型別

在golang中只有三種引用型別它們分別是切片slice、字典map、管道channel。其它的全部是值型別,引用型別可以簡單的理解為指標型別,它們都是通過make完成初始化 看下面兩個例子: a :=[5]int{2,3,4,5,6}

《Go語言核心36講》筆記8:陣列切片

回顧 前面幾節都是關於Go語言的基礎知識,包括開發環境配置、常用原始碼檔案語法,以及程式實體、變數及其相關概念和技巧(如型別推斷、變數重宣告、可重名變數、型別斷言、型別轉換、別名型別和潛在型別等),這些都是學習Go語言的基礎,務必要清楚每一個細節,也可以自己寫程式碼實踐一下

手把手golang教程【二】——陣列切片

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是golang專題的第五篇,這一篇我們將會了解golang中的陣列和切片的使用。 陣列與切片 golang當中陣列和C++中的定義類似,除了變數型別寫在後面。 比如我們要宣告一個長度為10的int型的陣列,會寫成這樣: var a

linux學習筆記--程序進程管理

ref monitor vim 子進程 free task 排序 image ctrl 、工作管理 1、前臺程序放後臺程序 命令後 加 & 2、任務執行時將前臺任務任務放到後臺中並【暫停】 ctr + z 3、jobs 觀察後臺工作狀態 及多少任務

golang學習筆記(1):安裝&helloworld

golang安裝:golang編譯器安裝過程比較簡單,也比較快,不同平臺下(win/linux/macos)都比較相似;https://dl.gocn.io/golang/1.9.2/go1.9.2.src.tar.gz 下載對應的系統版本的編譯器go的版本號由"." 分為3部分如當前的

學習筆記--概率期望

推廣 可能 試驗 同時 導致 取出 集合 .com strong 相關概念 基本事件ω(也稱樣本點): 一次試驗可能出現的每一個直接的 結果。也就是隨機試驗不能夠再分解的結果。 如:E1有兩個基本事件:E1 ={出現正面}, E2={出現反面}   E2有六個基本事件

shell腳本編程學習筆記-分支循環結構

linux shell 1.1 if語句 (1)if條件語句語法:單分支結構 if [ 條件 ] then 指令 fi 或 if [ 條件 ];then 指令 fi if 單分支條件中文編程形象語法 如果 [ 你有房 ] 那麽 我就嫁給你 果如 前面的文件條件表達式[ -f “$file1” ]&

ES6學習筆記----陣列的擴充套件

1、Array.from   應用兩類:類似於陣列的物件和可遍歷的的物件(包含Map和Set),只有轉換成真正的陣列,才可使用陣列的方法。      類比:...擴充套件運算子也可以使某些物件變成陣列 2、Array.of 主要彌補陣列建構函式Array(

Golang學習筆記(八)switch分支語句

Golang的switch可以不用在每個case裡寫一個break,Golang會自動加入。 default關鍵字可以帶,也可以不帶,不是必須要有的。 首先是一個最基礎的示例,在switch後面帶一個變數。 func ScoreGrade1() { gradel := "B" s

Golang學習筆記(七)if判斷語句

golang的判斷語句,不再需要用()來括起條件,但{必須跟if在一行。和java一樣,也有else關鍵字。 基礎例子,判斷奇偶數,給出一個值30,讓程式來判斷。 func EvenOdd(){ num := 30 if num % 2 == 0 { fmt.Println(nu

Golang學習筆記(六)運算子

實在是沒有什麼好寫的,寫幾個函式來體現幾個運算子。 新建一個go file,新增三個變數 var a = 21.0 var b = 5.0 var c float64 建一個函式來體現算術運算子 func Arithmetic() { c = a + b fmt.Printf

Golang學習筆記(五)常量及iota

Golang語言申明常量,需要用到一個關鍵字const。 const STR1 string = "hello" 大家習慣性的將常量設定為全大寫,但在Golang裡面是沒有private、public等許可權設定的,這些許可權僅靠方法、函式、變數等的首字母大小寫來設定,所以如果全大寫,將