ZetCode

Go Map

最后修改日期:2025 年 5 月 4 日

在本文中,我们将展示如何在 Golang 中使用 Map。

Go 中的 map 是一个无序的键/值对集合,其中每个键都是唯一的。Map 提供高效的查找、插入和删除,使其成为关联存储的基本数据结构。根据上下文,Map 也被称为 字典关联数组哈希表。Map 中的键值对数量可以使用内置的 len 函数来确定。

Map 使用 make 函数或 Map 字面量创建。make 函数初始化一个空的 Map

m := make(map[string]int)

或者,Map 字面量允许直接用预定义的键值对进行初始化

m := map[string]int{ "apple": 5, "banana": 3, "cherry": 7, }

要从 Map 中删除特定的键值对,可以使用内置的 delete 函数

delete(m, "banana")

如果指定的键在 Map 中不存在,delete 不执行任何操作。

Map 的默认零值为 nil,这意味着未初始化的 Map 没有分配存储空间,也不能直接修改。尝试向 nil Map 添加元素会导致运行时 panic。在使用 Map 之前,必须使用 make 初始化或分配一个有效的引用。

Go Map 对键查找提供恒定的时间复杂度,这使其在动态存储和检索结构化数据方面非常高效。但是,由于 Map 是无序的,它们的迭代顺序不保证,并且可能在不同执行之间有所不同。

Go Map 初始化

make 函数创建一个空的 Map。

init.go
package main

import "fmt"

func main() {

    var benelux map[string]string

    benelux = make(map[string]string)

    benelux["be"] = "Belgium"
    benelux["nl"] = "Netherlands"
    benelux["lu"] = "Luxembourgh"

    fmt.Println(benelux)
    fmt.Printf("%q\n", benelux)
}

我们有一个包含比荷卢经济联盟国家的 Map。

var benelux map[string]string

声明了一个字符串键和字符串值的 Map。

benelux = make(map[string]string)

使用 make 函数,我们创建了一个空的 Map。

benelux["be"] = "Belgium"
benelux["nl"] = "Netherlands"
benelux["lu"] = "Luxembourgh"

我们向 Map 中添加了三个键值对。

$ go run init.go
map[be:Belgium lu:Luxembourgh nl:Netherlands]
map["be":"Belgium" "lu":"Luxembourgh" "nl":"Netherlands"]
init2.go
package main

import "fmt"

func main() {

    benelux := make(map[string]string)

    benelux["be"] = "Belgium"
    benelux["nl"] = "Netherlands"
    benelux["lu"] = "Luxembourgh"

    fmt.Println(benelux)
    fmt.Printf("%q\n", benelux)
}

我们可以使用 := 操作符来简化语法。

Go Map 字面量

要使用字面量表示法创建和初始化 Map,我们在花括号 {} 中指定键/值对。键和值用冒号分隔。每对之间用逗号分隔。

literal.go
package main

import "fmt"

func main() {

    m := map[string]float64{
        "pi":  3.14159,
        "e":   2.71828,
        "ln2": 0.69314,
    }

    fmt.Println(m)
}

在代码示例中,我们使用 Map 字面量语法创建了一个常量 Map。

Go Map 大小

Map 的大小使用 len 函数确定。它返回 Map 中的键值对数量。

length.go
package main

import "fmt"

func main() {

    countries := map[string]string{
        "sk": "Slovakia",
        "ru": "Russia",
        "de": "Germany",
        "no": "Norway",
    }

    fmt.Printf("There are %d pairs in the map\n", len(countries))
}

在代码示例中,我们创建了一个国家 Map,其中国家代码是键,国家名称是值。我们打印 Map 中的国家数量。

$ go run length.go
There are 4 pairs in the map

Map 中有四个键/值对。

Go Map 循环

使用 forrange 关键字,我们可以遍历 Map 元素。

loop.go
package main

import "fmt"

func main() {

    countries := map[string]string{
        "sk": "Slovakia",
        "ru": "Russia",
        "de": "Germany",
        "no": "Norway",
    }

    for country := range countries {
        fmt.Println(country, "=>", countries[country])
    }

    for key, value := range countries {
        fmt.Printf("countries[%s] = %s\n", key, value)
    }
}

在代码示例中,我们以两种方式遍历国家 Map。

for country := range countries {
    fmt.Println(country, "=>", countries[country])
}

第一种情况,我们通过键值对对象进行迭代。

for key, value := range countries {
    fmt.Printf("countries[%s] = %s\n", key, value)
}

第二种情况,我们通过键和值进行迭代。

$ go run loop.go
de => Germany
no => Norway
sk => Slovakia
ru => Russia
countries[ru] = Russia
countries[de] = Germany
countries[no] = Norway
countries[sk] = Slovakia

Go Map 检查元素

我们通过引用键来检查值是否存在。如果左侧只有一个变量,我们将得到一个现有值或一个零值。如果左侧有两个变量,我们将得到值和一个布尔值,指示键在 Map 中的存在情况。

checking.go
package main

import "fmt"

func main() {

    grades := map[string]int{
        "Lucia": 2,
        "Paul":  1,
        "Merry": 3,
        "Jane":  1,
    }

    g := grades["Lucia"]
    fmt.Println(g)

    g = grades["Peter"]
    fmt.Println(g)

    g, found := grades["Lucia"]
    fmt.Println(g, found)

    g, found = grades["Peter"]
    fmt.Println(g, found)

    if g, found := grades["Jane"]; found {
        fmt.Println(g)
    }
}

在代码示例中,我们检查学生的成绩。

g := grades["Lucia"]
fmt.Println(g)

这里我们打印 Lucia 的成绩。

g = grades["Peter"]
fmt.Println(g)

由于 Peter 不在 Map 中,我们得到一个零值(整数为 0)。

g, found := grades["Lucia"]
fmt.Println(g, found)

g, found = grades["Peter"]
fmt.Println(g, found)

这里我们同时获取成绩和布尔值。

if g, found := grades["Jane"]; found {
    fmt.Println(g)
}

这是在 if 语句中获取布尔值并对其进行检查的简洁语法。

$ go run checking.go
2
0
2 true
0 false
1

Go Map 删除元素

使用 delete 函数从 Map 中删除元素。

removing.go
package main

import "fmt"

func main() {

    countries := map[string]string{
        "sk": "Slovakia",
        "ru": "Russia",
        "de": "Germany",
        "no": "Norway",
    }

    fmt.Println(countries)

    delete(countries, "ru")

    fmt.Println(countries)
}

在代码示例中,我们从国家 Map 中删除一个国家。

$ go run removing.go
map[de:Germany no:Norway ru:Russia sk:Slovakia]
map[de:Germany no:Norway sk:Slovakia]

俄罗斯已成功删除。

Go Map 是引用类型

Go Map 是引用类型。这意味着当我们为新变量赋值一个引用或将 Map 传递给函数时,Map 的引用会被复制。

reference.go
package main

import "fmt"

func main() {

    countries := map[string]string{
        "sk": "Slovakia",
        "ru": "Russia",
        "de": "Germany",
        "no": "Norway",
    }

    countries2 := countries

    countries2["us"] = "USA"

    fmt.Println(countries)
}

修改 countries2 Map(它是 countries 的引用)时,原始 Map 也会被修改。

Go 结构体 Map

在下面的示例中,我们使用结构体 Map。结构体是一种用户定义的类型,包含一组字段。它用于将相关数据组合成一个单一单元。

users.go
package main

import "fmt"

type User struct {
    name       string
    occupation string
}

func main() {

    u1 := User{
        name:       "John Doe",
        occupation: "gardener",
    }

    u2 := User{
        name:       "Richard Roe",
        occupation: "driver",
    }

    u3 := User{
        name:       "Lucy Smith",
        occupation: "teacher",
    }

    users := map[int]User{
        1: u1,
        2: u2,
        3: u3,
    }

    fmt.Println(users)
}

在代码示例中,我们有一个用户 Map。每个用户由一个 Go 结构体表示。

$ go run users.go 
map[1:{John Doe gardener} 2:{Richard Roe driver} 3:{Lucy Smith teacher}]

来源

Go Map 实战

在本文中,我们演示了如何在 Golang 中使用 Map。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写超过 1400 篇文章和 8 本电子书。我在编程教学方面拥有超过十年的经验。

列出所有 Go 教程