#### **數組介紹**
數組可以存放多個同一類型數據。數組也是一種數據類型,在Go中,數組是值類型。
看一個問題
一個養雞場有6只雞,它們的體重分別是3kg,5kg,1kg,3.4kg,2kg,50kg。請問這六只雞的總體重是多少?平均體重是多少?請你編一個程序。=》數組

對上面代碼的總結
1)使用數組來解決問題,程序的可維護性增加.
2)而且方法代碼更加清晰,也容易擴展。
**數組定義和內存布局**
var數組名\[數組大小\]數據類型
vara\[5\]int
初值a\[0\]=1a\[1\]=30....
數組在內存布局(重要)

對上圖的總結
1)數組的地址可以通過數組名來獲取&intArr
2)數組的第一個元素的地址,就是數組的首地址
3)數組的各個元素的地址間隔是依據數組的類型決定,比如int64->8int32->4..

**數組的使用**
數組名\[下標\]比如:你要使用a數組的第三個元素a\[2\]
**四種初始化數組的方式**

**數組的遍歷**
1:常規遍歷:for循環
2:for-range結構遍歷這是Go語言一種獨有的結構,可以用來遍歷訪問數組的元素。


**數組使用的注意事項和細節**
1)數組是多個相同類型數據的組合,一個數組一旦聲明/定義了,其長度是固定的,不能動態變化

2) var arr \[\]int 這時 arr 就是一個 slice 切片,切片后面專門講解,不急哈.
3) 數組中的元素可以是任何數據類型,包括值類型和引用類型,但是不能混用。
4) 數組創建后,如果沒有賦值,有默認值(零值)
數值類型數組:默認值為 0
字符串數組: 默認值為 ""
bool 數組: 默認值為 false

5) 使用數組的步驟 1\. 聲明數組并開辟空間 2 給數組各個元素賦值(默認零值) 3 使用數組
6) 數組的下標是從 0 開始的

7) 數組下標必須在指定范圍內使用,否則報 panic:數組越界,比如 var arr \[5\]int 則有效下標為 0-4
8) Go 的數組屬值類型, 在默認情況下是值傳遞, 因此會進行值拷貝。數組間不會相互影響

9) 如想在其它函數中,去修改原來的數組,可以使用引用傳遞(指針方式)

10) 長度是數組類型的一部分,在傳遞函數參數時 需要考慮數組的長度,看下面案例

#### **切片**
1) 切片的英文是 slice
2) 切片是數組的一個引用,因此切片是引用類型,在進行傳遞時,遵守引用傳遞的機制。
3) 切片的使用和數組類似,遍歷切片、訪問切片的元素和求切片長度 len(slice)都一樣。
4) 切片的長度是可以變化的,因此切片是一個可以動態變化數組。
5) 切片定義的基本語法: var 切片名 []類型 比如:var a [] int
**快速入門**

**切片在內存中形式(重要)**

對上面的分析圖總結
1. slice 的確是一個引用類型
2. slice 從底層來說,其實就是一個數據結構(struct 結構體)
```
type slice struct {
ptr *[2]int
len int
cap int
}
```
**切片的使用**
第一種方式:定義一個切片,然后讓切片去引用一個已經創建好的數組,比如前面的案例就是這樣的。
第二種方式:通過 make 來創建切片.
基本語法:var 切片名 []type = make([]type, len, [cap])
參數說明: type: 就是數據類型 len : 大小 cap :指定切片容量,可選, 如果你分配了 cap,則要求 cap>=len.

對上面代碼的小結:
1) 通過 make 方式創建切片可以指定切片的大小和容量
2) 如果沒有給切片的各個元素賦值,那么就會使用默認值\[int , float=> 0 string =>”” bool => false\]
3) 通過 make 方式創建的切片對應的數組是由 make 底層維護,**對外不可見,即只能通過 slice 去 訪問各個元素.**
第 3 種方式:定義一個切片,直接就指定具體數組,使用原理類似 make 的方式

方式 1 和方式 2 的區別(面試)

**切片的遍歷**
切片的遍歷和數組一樣,也有兩種方式
for 循環常規方式遍歷
for-range 結構遍歷切片

**切片的使用的注意事項和細節討論**
1) 切片初始化時 var slice = arr\[startIndex:endIndex\] 說明:從 arr 數組下標為 startIndex,取到 下標為 endIndex 的元素(不含 arr\[endIndex\])。
2) 切片初始化時,仍然不能越界。范圍在 \[0-len(arr)\] 之間,但是可以動態增長.
var slice = arr\[0:end\] 可以簡寫 var slice = arr\[:end\] var slice = arr\[start:len(arr)\] 可以簡寫: var slice = arr\[start:\] var slice = arr\[0:len(arr)\] 可以簡寫: var slice = arr\[:\]
3) cap 是一個內置函數,用于統計切片的容量,即最大可以存放多少個元素。
4) 切片定義完后,還不能使用,因為本身是一個空的,需要讓其引用到一個數組,或者 make 一 個空間供切片來使用
5) 切片可以繼續切片\[案例演示\]

6) 用 append 內置函數,可以對切片進行動態追加(注意直接下標得方式長度有限制長度為切片初始化的默認長度超過長度限制)


切片 append 操作的底層原理分析:
切片 append 操作的本質就是對數組擴容
go 底層會創建一下新的數組 newArr(安裝擴容后大小)
將 slice 原來包含的元素拷貝到新的數組 newArr
slice 重新引用到 newArr
注意 newArr 是在底層來維護的

7) 切片的拷貝操作
切片使用 copy 內置函數完成拷貝,舉例說明,程序員不可見

對上面代碼的說明:
(1) copy(para1, para2) 參數的數據類型是切片
(2) 按照上面的代碼來看, slice4 和 slice5 的數據空間是獨立,相互不影響,也就是說 slice4\[0\]= 999,
slice5\[0\] 仍然是 1
8) 關于拷貝的注意事項

9) 切片是引用類型,所以在傳遞時,遵守引用傳遞機制。看兩段代碼,并分析底層原理

**string 和 slice**
1) string 底層是一個 byte 數組,因此 string 也可以進行切片處理 案例演示:

2) string 和切片在內存的形式,以 "abcd" 畫出內存示意圖

3) string 是不可變的,也就說不能通過 str\[0\] = 'z' 方式來修改字符串

4) 如果需要修改字符串,可以先將 string -> []byte / 或者 []rune -> 修改 -> 重寫轉成 string

編寫一個函數 fbn(n int) ,要求完成
1) 可以接收一個 n int
2) 能夠將斐波那契的數列放到切片中
3) 提示, 斐波那契的數列形式:
arr[0] = 1; arr[1] = 1; arr[2]=2; arr[3] = 3; arr[4]=5; arr[5]=8

**二維數組**

**使用方式 1: 先聲明/定義,再賦值**
語法: var 數組名 [大小] [大小\]類型
比如: var arr [2][3]int , 再賦值。
使用演示
二維數組在內存的存在形式(重點)
解釋:指針是16進制顯示,兩個指針相差24個字節因為 int占8個3*8地址為第二個指針


**使用方式 2: 直接初始化**
聲明:var 數組名 \[大小\]\[大小\]類型 \= \[大小\]\[大小\]類型{{初值..},{初值..}}
賦值(有默認值,比如 int 類型的就是 0)

**二維數組在聲明/定義時也對應有四種寫法\[和一維數組類似\]**
var 數組名 \[大小\]\[大小\]類型 \= \[大小\]\[大小\]類型{{初值..},{初值..}}
var 數組名 \[大小\]\[大小\]類型 \= \[...\]\[大小\]類型{{初值..},{初值..}}
var 數組名 \= \[大小\]\[大小\]類型{{初值..},{初值..}}
var 數組名 \= \[...\]\[大小\]類型{{初值..},{初值..}}
**二維數組的遍歷**
雙層 for 循環完成遍歷
for-range 方式完成遍歷
