> For the complete documentation index, see [llms.txt](https://go.netdpi.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://go.netdpi.net/array_slice_map/map.md).

# 06.03-Map

Map 是一個無排序的 key-value 配對集合，也是所謂的一個有關聯的陣列、一個雜湊表或是一個目錄。map 可以使用一個關聯的 key 來查值，下列是一個 Go 語言的 map 範例：

```go
var x map[string]int
```

Map 的型別是透過 `map` 關鍵字表示，後面接著中括號框著的 key 型別，最後則是 value 的型別。可以這樣念，「`x` 是一個 `string` 對 `int` 的 map」。

如同陣列與 slice，可以使用中括號來存取 map，請試著執行下列的程式：

```go
var x map[string]int
x["key"] = 10
fmt.Println(x)
```

你應該會看到類似如下的錯誤訊息：

```go
panic: runtime error: assignment to entry in nil map

goroutine 1 [running]:
main.main()
  main.go:7 +0x4d

goroutine 2 [syscall]:
created by runtime.main
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindi
t269497170/go/src/pkg/runtime/proc.c:221
exit status 2
```

到目前為止，我們只看到編譯期的錯誤。這是一個執行期的錯誤訊息，如其名所示，執行期的錯誤會在執行程式期間發生，而編譯期的錯誤則是在編譯程式期間發生的。

我們程式的問題是，必須在使用 map 之前先進行初始化，我們應該改成下面的寫法：

```go
x := make(map[string]int)
x["key"] = 10
fmt.Println(x["key"])
```

你執行此程式之後應該會看到有 `10` 出現，陳述句 `x["key"] = 10` 跟我們在使用陣列時類似，只是這裡是 key 而不是整數，而且是一個字串，因為這裡 map 的 key 型別是 `string`。我們也可以使用 `int` 型別做為 key 來建立 map：

```go
x := make(map[int]int)
x[1] = 10
fmt.Println(x[1])
```

這樣看起來很像是一個陣列，不過還是有些不同之處。首先，map 的長度（透過 `len(x)` 取得）是可以改變的，只要我們新增項目（item）就會改變。起初 map 建立時的長度為 0，而在我們執行 `x[1] = 10` 之後，長度就變成 1 了。第二個與陣列的差異是，map 並非循序的，例如在陣列中，當看到 `x[1]` 代表的是一定有 `x[0]` 的存在不過 map 卻不一定如此。

我們也可以使用內建的 `delete` 函式來刪除 map 中的項目：

```go
delete(x, 1)
```

接著來看一個 map 範例程式：

```go
package main

import "fmt"

func main() {
    elements := make(map[string]string)
    elements["H"] = "Hydrogen"
    elements["He"] = "Helium"
    elements["Li"] = "Lithium"
    elements["Be"] = "Beryllium"
    elements["B"] = "Boron"
    elements["C"] = "Carbon"
    elements["N"] = "Nitrogen"
    elements["O"] = "Oxygen"
    elements["F"] = "Fluorine"
    elements["Ne"] = "Neon"
    
    fmt.Println(elements["Li"])
}
```

`elements` 是一個 map，使用化學元素表的前十個元素符號做為 elaments 的索引值，這是常見的 map 用法：如同查表或是查字典。假設我們查詢了一個不存在的元素：

```
fmt.Println(elements["Un"])
```

若是執行上面這行程式，應該不會傳回任何資料。技術上，一個 map 會依據 value 的型別而傳回相對應的零值（比如字串就是傳回空字串）。雖然我們可以透過條件式來檢查零值（`elements["Un"] == ""`），不過 Go 語言有提供一個更好的方法：

```go
name, ok := elements["Un"]
fmt.Println(name, ok)
```

存取一個 map 中的一個元素可以傳回兩個值，第一個值是查詢的結果，而第二個值是告訴我們查詢是否成功。在 Go 語言中，我們通常會看到下列這樣的程式碼：

```go
if name, ok := elements["Un"]; ok {    
    fmt.Println(name, ok)
}
```

首先，我們試著存取 map 的值，若成功了，則執行區塊中的程式碼：

如同我們在介紹陣列時所見，也有比較簡潔的方式可以建立 map：

```go
elements := map[string]string{
    "H": "Hydrogen",
    "He": "Helium",
    "Li": "Lithium",
    "Be": "Beryllium",
    "B": "Boron",
    "C": "Carbon",
    "N": "Nitrogen",
    "O": "Oxygen",
    "F": "Fluorine",
    "Ne": "Neon",
}
```

一般會將 map 用來儲存通用的資訊，現在來修改我們的程式，使得元素不僅可以儲存名稱，還可以儲存其標準狀態（室溫狀態）：

```go
func main() {
    elements := map[string]map[string]string{
        "H": map[string]string{
            "name":"Hydrogen", 
            "state":"gas",
        },
        "He": map[string]string{
            "name":"Helium", 
            "state":"gas",
        },
        "Li": map[string]string{
            "name":"Lithium", 
            "state":"solid",
        },
        "Be": map[string]string{
            "name":"Beryllium", 
            "state":"solid",
        },
        "B":  map[string]string{
            "name":"Boron",
            "state":"solid",
        },
        "C":  map[string]string{
            "name":"Carbon",
            "state":"solid",
        },
        "N":  map[string]string{
            "name":"Nitrogen",
            "state":"gas",
        },
        "O":  map[string]string{
            "name":"Oxygen",
            "state":"gas",
        },
        "F":  map[string]string{
            "name":"Fluorine",
            "state":"gas",
        },
        "Ne":  map[string]string{
            "name":"Neon",
            "state":"gas",
        },
    }

    if el, ok := elements["Li"]; ok {    
        fmt.Println(el["name"], el["state"])
    }
}
```

要注意，我們的 map 型別已經從 `map[string]string` 改為 `map[string]map[string]string`。現在我們有一個兩層的字串 map ，外部的 map 用來查表（基於元素的符號），而內部的 map 則用來儲存與元素相關的通用資訊，雖然通常都會這樣使用 map，不過我們在第9章會再探討儲存結構化資訊的較好方法。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://go.netdpi.net/array_slice_map/map.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
