開放原始碼技術文件網 使用映射 (Map)

最後修改日期為 JUN 2, 2019

前言

在上一篇文章中,我們介紹了兩個線性的容器:陣列和切片,這兩個容器皆以數字為索引。在本文中,我們會介紹映射 (map),這是另外一種容器;映射儲存鍵/值 (key/value) 對,可以用數種資料型別做為鍵,取得相對應的值。

註:map 有些教材不翻,也有些教材翻成映射,本文取後者;相同的概念可見於 Python 的字典 (dictionary)、Perl 的雜湊 (hash) 和 PHP 的關連性陣列 (associative array) 等。

建立映射

以下實例建立一個以字串為鍵、以字串為值的映射,接著檢查某組鍵值對是否存在:

package main
 
import (
    "log"
)
 
func main() {
    // Declare an empty map.
    m := make(map[string]string)
 
    // Insert key/value pairs
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    // Call the value by the key.
    if !(m["Go"] == "Beego") {
        log.Fatal("Wrong value")
    }
 
}

檢查鍵值對是否為空

如果鍵/值對不存在,會依映射的值的型別回傳預設值。在此例中,回傳空字串:

package main
 
import (
    "log"
)
 
func main() {
    m := make(map[string]string)
 
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    // No such key/value pair.
    if !(m["Java"] == "") {
        log.Fatal("Wrong value")
    }
}

如果不確定鍵/值對是否存在,可以用以下語法檢查:

package main
 
import (
    "log"
)
 
func main() {
    m := make(map[string]string)
 
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    v, ok := m["Go"]
    if !ok {
        log.Fatal("It should be true")
    }
 
    if !(v == "Beego") {
        log.Fatal("Wrong value")
    }
 
    _, ok = m["Java"]
    if !(ok == false) {
        log.Fatal("It should be false")
    }
}

移除鍵值對

我們也可以用 delete 函式去除鍵/值對:

package main
 
import (
    "log"
)
 
func main() {
    m := make(map[string]string)
 
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    _, ok := m["PHP"]
    if !ok {
        log.Fatal("It should exist")
    }
 
    // Remove the key/value pair.
    delete(m, "PHP")
 
    _, ok = m["PHP"]
    if !(ok == false) {
        log.Fatal("It should not exist")
    }
}

映射的鍵/值對是單向的,我們僅能由鍵得到值,但不能由值得到鍵;另外,鍵不能重覆,但值可以。

走訪映射

類似於陣列和切片,我們也可以用迭代器走訪映射:

package main
 
import (
    "fmt"
)
 
func main() {
    m := make(map[string]string)
 
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    for k, v := range m {
        fmt.Println(fmt.Sprintf("%s: %s", k, v))
    }
}

要注意的是,映射是無序的,我們多執行幾次,就會發現每次的順序都不一樣,見下例:

package main
 
import (
    "fmt"
)
 
func main() {
    m := make(map[string]string)
 
    m["Go"] = "Beego"
    m["Python"] = "Django"
    m["Ruby"] = "Rails"
    m["PHP"] = "Laravel"
 
    for i := 0; i < 10; i++ {
        for k, v := range m {
            fmt.Println(fmt.Sprintf("%s: %s", k, v))
        }
 
        fmt.Println("")
    }
}

如果想要保持鍵/值對的順序,我們要額外儲存鍵在一個切片中,見下例:

package main
 
import "fmt"
 
func main() {
    // Create an anomynous struct.
    data := struct {
        m     map[string]string
        order []string
    }{
        m:     make(map[string]string),
        order: []string{},
    }
 
    // Insert several key/value pairs.
    data.m["Go"] = "Beego"
    data.order = append(data.order, "Go")
 
    data.m["Python"] = "Django"
    data.order = append(data.order, "Python")
 
    data.m["Ruby"] = "Rails"
    data.order = append(data.order, "Ruby")
 
    data.m["PHP"] = "Laravel"
    data.order = append(data.order, "PHP")
 
    // Iterate these key/value pairs with order.
    for _, e := range data.order {
        fmt.Println(fmt.Sprintf("%s: %s", e, data.m[e]))
    }
}

在本例中,我們用一個結構體一併儲存映射和切片。我們會在後文介紹結構體。

結語

藉由本文的介紹,相信各位讀者可以知道映射如何使用。由於映射相當實用,各位讀者可以多多練習,以熟悉映射的使用方式。

分享本文
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
追蹤本站
Facebook Facebook Twitter