1.數組是一系列同一類型數據的集合html
2.數組中包含的每一個數據被稱爲數組元素數組
3.一個數組中包含的元素個數成爲數組長度app
4.數組的長度是固定的ide
5.一個數組能夠由零個或者多個元素組成 函數
var arr [10]int //10個元素的整型數組 var ptrs [5]*float64 //5個元素的指針數組,每一個指針都指向float64類型 var points [8]struct{ x, y int } //8個元素的結構體類型 var arry [2][3]int //2*3的二維整型數組 a := [3]int{1, 2, 3} // 長度爲3的數組 b := [5]int{1, 2, 3} //長度爲10,前三個元素爲一、二、3,其它默認爲0 c := [...]int{4, 5, 6} //長度3的方式,Go自動計算長度 r := [...]int{9: 6} //長度爲10,最後一個元素的值爲6,其它默認爲0 arr2 := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}//二維數組
在Go語言中,數組長度在定義後就不可更改,在聲明時長度能夠爲一個常量或者一個常量表達式。性能
//申明數組 var a [5]byte //長度爲5的數組,每一個元素爲一個字節 var d [2][3]int //二維數組 //初始化數組 a = {'1','2','3'} d = {{1,2,3},{4,5,6}}
a := [3]byte{'1', '2', '3'} //聲明並初始化一個長度爲3的byte數組 a := [...]byte{'1', '2', '3'} //能夠省略長度而採用`...`的方式,Go會自動根據元素個數來計算長度 d := [2][3]int{[3]int{1,2,3},[3]int{4,5,6}} d := [2][3]int{{1,2,3},{4,5,6}} //若是內部的元素和外部的同樣,那麼上面的聲明能夠簡化,直接忽略內部的 類型
1.可使用數組下標來訪問數組中的元素spa
2.數組下標從0開始.net
3.len(arr)-1則表示最後一個元素的下標3d
package main import ( "fmt" ) func main() { var result int arr := [...]int{1, 2, 3, 4, 5} len := len(arr) //len獲取數組長度 fmt.Println("修改前:", arr) arr[0] = 100 //下標訪問數組元素 result = arr[3] //取出下標爲3的元素並賦值 fmt.Println("修改後:", arr) fmt.Println("數組長度:", len) fmt.Println("方位下標爲三的元素:",result) } //運行結果 //修改前: [1 2 3 4 5] //修改後: [100 2 3 4 5] //數組長度: 5 //方位下標爲三的元素: 4
package main import( "fmt" ) func main(){ arr := [...]int {9: 1} fmt.Println(arr) fmt.Println(len(arr)) } //運行結果 //[0 0 0 0 0 0 0 0 0 1] //10
package main import( "fmt" ) func main(){ arr := [5]int {1, 2, 3, 4, 5} for i := 0; i < len(arr); i++{ fmt.Printf("arr[%d]=%d\n", i, arr[i]) } } //運行結果 //arr[0]=1 //arr[1]=2 //arr[2]=3 //arr[3]=4 //arr[4]=5
package main import( "fmt" ) func main(){ arr := [5]int {1, 2, 3, 4, 5} for i, v := range(arr) { fmt.Printf("arr[%d]=%d\n", i, v) } } //運行結果 //arr[0]=1 //arr[1]=2 //arr[2]=3 //arr[3]=4 //arr[4]=5
1.數組做爲函數的參數仍然是值傳遞(值傳遞是複製數組給函數,傳遞後數組跟原數組沒有關係)指針
2.雖然可使用數組的指針來代替,可是改變不了數組長度。(能夠改變數組內的值,可是不能改變數組的長度)
package main import "fmt" func main() { arr1 := [5]int{1, 2, 3, 4, 5} fmt.Println("交換前arry1= " ,arr1) swap(arr1 ) fmt.Println("交換後arry1= " ,arr1) } func swap(a [5]int) { arr3 := a fmt.Println("值傳遞交換前arr3= ",arr3) c := arr3[0] arr3[0] = arr3[4] arr3[4] = c fmt.Println("值傳遞交換後arr3= ",arr3) } //運行結果 //交換前arry1= [1 2 3 4 5] //值傳遞交換前arr3= [1 2 3 4 5] //值傳遞交換後arr3= [5 2 3 4 1] //交換後arry1= [1 2 3 4 5]
package main import "fmt" func main() { arr1 := [5]int{1, 2, 3, 4, 5} fmt.Println("交換前arry1= " ,arr1) swap_pointer(&arr1 ) fmt.Println("交換後arry1= " ,arr1) } func swap_pointer(a *[5]int) { var arr3 *[5]int arr3 = a fmt.Println("指針傳遞交換前arr3= ",arr3) c := arr3[0] arr3[0] = arr3[4] arr3[4] = c fmt.Println("指針傳遞交換後arr3= ",arr3) } //運行結果 //交換前arry1= [1 2 3 4 5] //指針傳遞交換前arr3= &[1 2 3 4 5] //指針傳遞交換後arr3= &[5 2 3 4 1] //交換後arry1= [5 2 3 4 1]
1.若是數組元素的類型是可比較的,那麼這個數組也是可的比較
2.只有數組的全部元素都相等數組纔是相等的。
3.因爲長度也是數組類型的一部分,因此長度不一樣的數組是不等的。
4.數組可遍歷、可修改,是否可比較,由數組元素決定。
5.%T用於顯示一個值對應的數據類型。
1.數組的長度在定義以後沒法修改。
2.數組是值類型,每次傳遞都將產生一份副本。
3.顯然這沒法知足開發者的某些需求。
1.切片(Slice)是一個擁有相同類型元素的可變長度的序列。
2.Go語言切片的內部結構包含地址、大小和容量。
3.切片通常用於快速地操做一塊數據集合。
4.slice 老是指向底層的一個 array。
5.slice自己不是數組,slice 是一個指向 array的指針。
切片結構和內存分佈示意圖
slice [開始位置:結束位置:容量]
a. slice 表示目標切片對象
b. 開始位置對應目標切片對象的索引
c. 結束位置對應目標切片的結束索引
package main import "fmt" func main() { var a = [5]int{1,2,3} var c []int c = a[1:4:5] fmt.Println("c的長度爲:%d",len(c)) fmt.Println("c的容量爲:%d",cap(c)) fmt.Printf("c的類型:%T",c) } //運行結果 //c的長度爲:%d 3 //c的容量爲:%d 4 //c的類型:[]int
從數組或切片生成新的切片擁有以下特性
a.取出的元素數量爲:結束位置-開始位置
b.取出元素不包含結束位置對應的索引,切片最後一個元素使用 slice[len(slice)] 獲取
c.當缺省開始位置時,表示從連續區域開頭到結束位置
d.當缺省結束位置時,表示從開始位置到整個連續區域末尾
e.二者同時缺省時,與切片自己等效
f.二者同時爲0時,等效於空切片,通常用於切片復位
(ps:根據索引位置取切片 slice 元素值時,取值範圍是(0~len(slice)-1),超界會報運行時錯誤。生成切片時,結束位置能夠填寫 len(slice) 但不會報錯。)
每一種類型均可以擁有其切片類型,表示多個類型元素的連續集合。
var name []T //name 表示切片類型的變量名。 //T 表示切片類型對應的元素類型。
package main import "fmt" func main() { // 聲明字符串切片 var strList []string // 聲明整型切片 strList = []string{"asa","esd"} var numList []int // 聲明一個空切片 numListEmpty := []int{1,2,3} // 輸出3個切片 fmt.Println(strList, numList, numListEmpty) // 輸出3個切片大小 fmt.Println(len(strList), len(numList), len(numListEmpty)) // 切片斷定空的結果 fmt.Println(strList == nil) fmt.Println(numList == nil) fmt.Println(numListEmpty == nil) } //運行結果 //[asa esd] [] [1 2 3] //2 0 3 //false //true //false
ps: 1. 切片是動態結構,只能與nil斷定相等,不能互相判等。
2. 聲明新的切片後,可使用append() 函數來添加元素。
語法:
make( []T, size, cap )
T:切片的元素類型
size:就是爲這個類型分配多少個元素
cap:預分配的元素數量,這個值設定後不影響 size,只是能提早分配空間,下降屢次分配空間形成的性能問題
package main import "fmt" func main() { a := make([]int, 2) b := make([]int, 2, 10) fmt.Println(a, b) fmt.Println(len(a), len(b)) } //運行結果 //[0 0] [0 0] //2 2
1. a 和 b 均是預分配 2 個元素的切片,只是 b 的內部存儲空間已經分配了 10 個,但實際使用了 2 個元素。
2. 容量不會影響當前的元素個數,所以 a 和 b 取 len 都是 2。
(ps:使用 make() 函數生成的切片必定發生了內存分配操做。但給定開始與結束位置(包括切片復位)的切片只是將新的切片結構指向已經分配好的內存區域,設定開始與結束位置,不會發生內存分配操做。)
1.append() 能夠爲切片動態添加元素。
2.每一個切片會指向一片內存空間,這片空間能容納必定數量的元素。
3.當空間不能容納足夠多的元素時,切片就會進行「擴容」。
4.「擴容」操做每每發生在 append() 函數調用時。
package main import "fmt" func main() { //聲明一個整型切片。 var numbers []int for i := 0; i < 10; i++ { //循環向 numbers 切片添加10個數。 numbers = append(numbers, i) //打印輸出切片的長度、容量和指針變化。使用 len() 函數查看切片擁有的元素個數,使用 cap() 函數查看切片的容量狀況 fmt.Printf("len: %d cap: %d pointer: %p\n", len(numbers), cap(numbers), numbers) } } //運行結果 //len: 1 cap: 1 pointer: 0xc00001c060 //len: 2 cap: 2 pointer: 0xc00001c090 //len: 3 cap: 4 pointer: 0xc000016120 //len: 4 cap: 4 pointer: 0xc000016120 //len: 5 cap: 8 pointer: 0xc00001e180 //len: 6 cap: 8 pointer: 0xc00001e180 //len: 7 cap: 8 pointer: 0xc00001e180 //len: 8 cap: 8 pointer: 0xc00001e180 //len: 9 cap: 16 pointer: 0xc000088000 //len: 10 cap: 16 pointer: 0xc000088000
a.len() 函數並不等於 cap。
b.當元素個數超過cap()的數量時,切片會進行擴容
c.擴容後切片的內存地址發生改變
d.可是切片的名稱沒有發生改變。
package main import "fmt" func main() { var car []string // 添加1個元素 car = append(car, "OldDriver") // 添加多個元素 car = append(car, "Ice", "Sniper", "Monk") // 添加切片 team := []string{"Pig", "Flyingcake", "Chicken"} car = append(car, team...) fmt.Println(car) } //運行結果 //[OldDriver Ice Sniper Monk Pig Flyingcake Chicken]
在team後面加上了...
,表示將 team 整個添加到 car 的後面。