Skip to content

Go Map

Go 提供了一个强大的内置数据类型,称为 map。map 存储键值对(key-value pairs)的集合。在其他语言中,map 也被称为哈希表(hash map)或字典(dictionary)。map 中的键(key)必须是唯一的,并且必须是可比较的类型(例如,字符串、整数、布尔值、指针、包含可比较字段的结构体 struct)。值(value)可以是任何类型。

map 必须在使用前进行初始化。使用 make 函数是创建已初始化 map 的标准方式。未初始化的 map 的值为 nil,尝试向 nil map 添加元素将导致运行时 panic。

// Declare a map variable (it will be nil by default)
var countryCapitalMap map[string]string
// Initialize the map using make
countryCapitalMap = make(map[string]string)
// Alternatively, declare and initialize in one step
// capitals := make(map[string]string)
// You can also initialize a map with values using a map literal:
capitals := map[string]string{
"France": "Paris",
"Japan": "Tokyo",
}

此示例演示了如何创建 map、添加键值对、访问值、检查键是否存在以及遍历 map。

package main
import "fmt"
func main() {
// Create and initialize a map using make
countryCapitalMap := make(map[string]string)
// Insert key-value pairs into the map
countryCapitalMap["France"] = "Paris"
countryCapitalMap["Italy"] = "Rome"
countryCapitalMap["Japan"] = "Tokyo"
countryCapitalMap["India"] = "New Delhi"
// Print map using keys (iteration order is not guaranteed)
fmt.Println("Iterating through the map:")
for country, capital := range countryCapitalMap {
fmt.Printf("Capital of %s is %s\n", country, capital)
}
// Accessing a value
fmt.Println("\nCapital of Japan is:", countryCapitalMap["Japan"])
// Checking if a key exists (the "comma ok" idiom)
// If a key doesn't exist, accessing it directly returns the zero value for the value type.
// To distinguish between a stored zero value and a non-existent key, use the two-value assignment.
capital, ok := countryCapitalMap["United States"]
if ok {
fmt.Println("Capital of United States is", capital)
} else {
fmt.Println("Capital of United States is not present in the map.")
}
// Accessing a non-existent key without the "comma ok" idiom returns the zero value
// For string values, the zero value is an empty string.
fmt.Println("Capital of Germany (not present): '", countryCapitalMap["Germany"], "'")
}

编译并执行上述代码后,会产生类似于以下的结果(注意:map 的遍历顺序是随机的):

Iterating through the map:
Capital of India is New Delhi
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of Japan is: Tokyo
Capital of United States is not present in the map.
Capital of Germany (not present): ''

内置的 delete() 函数从 map 中删除一个条目。它接受 map 和要删除的键(key)作为参数。如果 map 中不存在该键,delete() 函数是一个空操作(no-op),它不做任何事情,也不会引起 panic。

package main
import "fmt"
func main() {
// Initialize a map using a map literal
countryCapitalMap := map[string]string{
"France": "Paris",
"Italy": "Rome",
"Japan": "Tokyo",
"India": "New Delhi",
}
fmt.Println("Original map:")
for country, capital := range countryCapitalMap {
fmt.Printf("Capital of %s is %s\n", country, capital)
}
// Delete an entry
delete(countryCapitalMap, "France")
fmt.Println("\nEntry for France is deleted.")
// Delete a non-existent entry (no error)
delete(countryCapitalMap, "Germany")
fmt.Println("Attempted to delete entry for Germany (no error if not present).")
fmt.Println("\nUpdated map:")
for country, capital := range countryCapitalMap {
fmt.Printf("Capital of %s is %s\n", country, capital)
}
}

编译并执行上述代码后,会产生类似于以下的结果(遍历顺序可能有所不同):

Original map:
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted.
Attempted to delete entry for Germany (no error if not present).
Updated map:
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi

关于 Map 的额外注意事项:

  • 可比较的键(Comparable Keys):map 的键必须是支持比较(即 == 和 != 运算符)的类型。切片(slices)、map 和函数不能用作 map 的键。
  • 并发性(Concurrency):map 对于并发读写访问不是安全的。如果多个 goroutines 同时访问一个 map,必须使用互斥锁(mutexes,例如 sync.RWMutex)来同步访问,或者在特定并发使用场景下使用 sync.Map。
  • 零值(Zero Value):map 类型的零值是 nil。一个 nil map 不包含任何键,也不能向其添加键。