---
# System prepended metadata

title: array、slice、map

---

# array、slice、map

golang複合型別包括：陣列、切片、Maps、結構體。

## 陣列(Array)
陣列(Array)是一個固定空間(建立後不能改變長度)的容器，在同一個陣列裡的所有元素型態皆相同。

陣列中的元素可以透過索引(index)來操作，索引從 `0` 開始。

| 第一個元素 | 第二個元素 | 第三個元素 | 第四個元素 | 第五個元素 |
| -------- | -------- | -------- | -------- | -------- |
| arr[0]     | arr[1]     | arr[2]     | arr[3]     | arr[4]

### 宣告陣列

宣告長度為10 整數型態的陣列：

```go=
var arr [10]int // 使用var關鍵字宣告
arr := [10]int{} // 簡化宣告
```

Go語言宣告陣列時必須給定陣列大小以及型態。

```go=
var arr [10]int
arr[0] = 49
arr[1] = 55
fmt.Printf(arr[0])  // 49
fmt.Printf(arr[1]) // 55
fmt.Printf(arr[9]) // 未賦予值，預設為 0 
```

### 陣列初始化

將等號擺在型態以及大小的左邊，並且使用 `{ }` 括住陣列元素，每個元素以 `,` 隔開。

```go=
var arr = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
arr2 := [10]int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
```

當不知道這個陣列要多長時，可以使用 `[...]` 來讓 Go自行偵測你的陣列中有多少元素。

```go=
arr := [...]int{10, 11, 12, 13, 14}
len(arr) // len可用於獲取容器長度 , arr陣列的長度為 5
```

### 多維陣列

Go還支援巢狀陣列(多維陣列)

```go=
doubleArr := [2][3]int{{55, 56, 57}, {58, 59, 60}}
fmt.Println(doubleArr, len(doubleArr)) // 印出陣列為 [[55 56 57] [58 59 60]] 長度為 2
fmt.Println(doubleArr[0]) // 輸出二維陣列索引第0個元素為 [55,56,57]
fmt.Println(doubleArr[0][2]) // 輸出為第0個元素中的第2個元素 為 57
```

### 走訪陣列

因為還沒說到迴圈的部分，先簡單帶一下，或者有其他程式語言經驗的話應該就很好懂了。

Go語言的 for 迴圈語法為：

```go=
for i := 0 ; i < 10 ; i++ {
	//code
}
```

使用迴圈走訪 arr 陣列並印出陣列中的所有值：

```go=
arr := [10]int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

for i := 0; i < len(arr); i++ {
	fmt.Print(arr[i], " ") //印出 10 11 12 13 14 15 16 17 18 19
}
```

for迴圈也可以簡化成下面的方式

index可以用 `_` 下划線取代，意即 blank identifier(啞變數)，代表我不需要使用這個變數。而 number 才是陣列的值。

```go=
arr := [10]int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
for index, number := range arr {
	fmt.Print(fmt.Sprintf("%d : %d / ", index, number))
}
```

### 驗收

我在leetcode上找了一題難易度為easy的array題來試了一下，下面的code是我最先想到的寫法，但並不是很優，未來待我水平提高之後再回來重寫。

> **1480.Running Sum of 1d Array**
> 
> Given an array nums. We define a running sum of an array as runningSum[i] = sum(nums[0]…nums[i]).
> Return the running sum of nums.
> 
> **Example 1:**
> 
> Input: nums = [1,2,3,4]
> Output: [1,3,6,10]
> Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].
> 
> **Example 2:**
> 
> Input: nums = [1,1,1,1,1]
> Output: [1,2,3,4,5]
> Explanation: Running sum is obtained as follows: [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1].
> 
> **Example 3:**
> 
> Input: nums = [3,1,2,10,1]
> Output: [3,4,6,16,17]
> 
> **Constraints:**
> 
> 1 <= nums.length <= 1000
> -106 <= nums[i] <= 106

sol：

```go=
func runningSum(nums []int) []int {
    var allsum int
    output := []int{}
    
    for i:=0 ; i<len(nums) ; i++{
        allsum += nums[i]
        output = append(output,allsum)
    }
    
    return output
}
```

## 切片(Slice)

Slice其實就是List，與Array不同的地方在於它的長度是可變的，而Array定義多長就是多長。

### 宣告切片

跟Array的宣告方式一樣，只差在切片不需要宣告長度

```go=
var slice1 []int //與宣告Array只差在沒有長度
```

也可以使用 `make()` 函數來創建切片(可給予長度)

```go=
var slice2 []int = make([]int,10)
// 簡寫為
slice2 := make([]int,10)
```

### 初始化切片

與Array相同，差別只在沒有給予長度。

```go=
slice := []int{1, 2, 3, 4, 5}
fmt.Print(slice) //[1 2 3 4 5]
```

使用 `slice[ i : j ]` 指定輸出這個切片索引 i ~ (j-1) 的元素，`slice[1:3]` 輸出為 [2 3]
`slice[i: ]` 代表創建從 i 元素開始直到最後一個元素的切片
`slice[ :j]` 代表創建從 0 直到 j-1 元素的切片
`slice[:]` 包含所有slice內的元素

```go=
slice := []int{1, 2, 3, 4, 5}
fmt.Print(slice[1:3]) // [2 3]
fmt.Print(slice[1:]) // [2 3 4 5]
fmt.Print(slice[:3]) // [1 2 3]
fmt.Print(slice[:]) // [1 2 3 4 5]
```

### 新增元素

可以使用 `append` 向切片裡追加一個至多個元素：

```go=
slice1 := []int{1, 2, 3, 4, 5}
fmt.Print(slice1[:]) // [1 2 3 4 5]
slice1 = append(slice1, 6, 7, 8, 9, 10)
fmt.Print(slice1[:]) // [1 2 3 4 5 6 7 8 9 10]
```

允許追加空切片，即 `append(slice1 , 0)`

Go中沒有移除元素的函式，但我們可以透過取索引時忽略該元素來達到移除該元素的目的。

```go=
slice1 = append(slice1[0:2], slice1[3:5]) //slice1[2] 被移除了
```

## 映射(Map)

Map是一種**無序**的鍵值對集合，map最重要的一點是通過 key 來快速檢索數據，類似陣列和切片的索引，指向數據的值。

### 定義方式

#### 第一種

首先定義一個Map變數，但值為空。我們需要通過 `make` 來開闢內部空間並做基本的賦值

```go=
var myMap map[string]string
//在使用map前需要先用make給map分配數據空間
myMap = make(map[string]string, 10)

myMap["name"] = "小明"
myMap["address"] = "台灣新北市"
myMap["phone"] = "0905123456"

fmt.Println(myMap) //map[address:台灣新北市 name:小明 phone:0905123456]
```
當**鍵值對不存在** 或者 **沒有初始化map** , 會回傳預設值`nil`


```go=
if myMap == nil{
	fmt.Println("myMap是一個空map")
}
```

你會發現打印出來的順序並非按照程式碼所寫的順序，這是因為map是使用**雜湊函式(hash)**來實現的。

#### 第二種
直接通過 定義變數 `make` 創建map型別變數再去賦值。

```go=
myMap2 := make(map[int]string) //可以不用分配空間大小, 默認會分配一些
myMap2[1] = "小明"
myMap2[2] = "台灣新北市"
myMap2[3] = "0905123456"

fmt.Println(myMap2) //map[1:小明 2:台灣新北市 3:0905123456]
```

#### 第三種
在定義map的時候直接使用` { } `新增鍵值對初始化，在初始化過程時已經開闢了空間因此不需要使用`make`。

```go=
myMap3 := map[string] string{
	"name": "小明",
	"address": "台灣新北市",
	"phone": "0905123456",
}

fmt.Println(myMap3) //map[address:台灣新北市 name:小明 phone:0905123456]
```

注意每一個鍵值對後方都要加上 `,` 包括最後一個鍵值對也是。

### 使用方式

#### 新增元素

使用 `mapName[key] = value` 新增元素

```go=
var myMap = make(map[string]string, 10)
myMap["name"] = "小明"
myMap["address"] = "台灣新北市"
myMap["phone"] = "0905123456"
fmt.Println(myMap) //map[address:台灣新北市 name:小明 phone:0905123456]

myMap2 := make(map[int]string)
myMap2[1] = "小明"
myMap2[2] = "台灣新北市"
myMap2[3] = "0905123456"
fmt.Println(myMap2) //map[1:小明 2:台灣新北市 3:0905123456]

myMap3 := map[string] string{
    "name": "小明",
    "address": "台灣新北市",
    "phone": "0905123456",
}
myMap3["email"] = "pluto@gmail.com"
fmt.Println(myMap3) //map[address:台灣新北市 email:pluto@gmail.com name:小明 phone:0905123456]
```

#### 刪除元素

`delete(mapName, key)` 函數用於刪除集合的元素，參數為Map和其對應的key

```go=
myMap3 := map[string] string{
	"name": "小明",
	"address": "台灣新北市",
	"phone": "0905123456",
}

delete(myMap, "address")

fmt.Println(myMap3)
```

#### 修改元素

與新增元素的方式一樣，差別只在key為想要修改的鍵值對的key

```go=
myMap3 := map[string]string{
	"name":    "小明",
	"address": "台灣新北市",
	"phone":   "0905123456",
}

myMap3["name"] = "小王"
fmt.Println(myMap3) //map[address:台灣新北市 name:小王 phone:0905123456]
```

#### 走訪

可以用迭代器走訪映射：

```go=
myMap2 := make(map[string]string)
myMap2["name"] = "小明"
myMap2["address"] = "台灣新北市"
myMap2["phone"] = "0905123456"

//利用 rage 取得 map 中所有的 key 和 value, 並列印
for key, value := range myMap2 {
	fmt.Println(fmt.Sprintf("%s: %s", key, value))
}
```

```go=
name: 小明
address: 台灣新北市
phone: 0905123456
```