04.Map
在 Go 语言中,map
是一种内置的数据结构,用于存储键值对。map
提供了高效的键值对查询、插入和删除操作。下面是详细介绍 map
的使用方法及注意事项。
1. 创建和初始化 map
使用 make
函数创建
可以使用 make
函数创建一个指定类型的 map
。
package main import "fmt" func main() { // 创建一个 key 为 string, value 为 int 的 map myMap := make(map[string]int) fmt.Println(myMap) // 输出:map[] }
使用字面量初始化
可以直接使用字面量初始化一个 map
,同时设置初始值。
package main import "fmt" func main() { myMap := map[string]int{ "one": 1, "two": 2, "three": 3, } fmt.Println(myMap) // 输出:map[one:1 two:2 three:3] }
在 Go 语言中,
map
是无序的。每次遍历或打印map
中的键值对时,它们的顺序可能不同。这个特性是由 Go 语言的内部实现决定的。即使你使用相同的代码,多次运行也可能得到不同的键值对顺序。具体原因如下:
内部哈希实现:
map
的键是通过哈希算法计算得到的,而哈希算法的结果在内存布局中并不保证顺序。优化性能:Go 语言的
map
实现为了优化性能和内存使用,没有对键值对进行排序。因此,每次遍历或打印时的顺序可能不同。
2. 操作 map
添加和更新元素
使用 map[key] = value
的语法添加或更新 map
中的元素。
package main import "fmt" func main() { myMap := make(map[string]int) myMap["one"] = 1 myMap["two"] = 2 fmt.Println(myMap) // 输出:map[one:1 two:2] // 更新元素 myMap["one"] = 10 fmt.Println(myMap) // 输出:map[one:10 two:2] }
访问元素
使用 map[key]
的语法访问 map
中的元素。可以使用两个返回值的方式来判断键是否存在。
package main import "fmt" func main() { myMap := map[string]int{"one": 1, "two": 2} value := myMap["one"] fmt.Println("Value for 'one':", value) // 输出:Value for 'one': 1 // 判断键是否存在 value, ok := myMap["three"] if ok { fmt.Println("Value for 'three':", value) } else { fmt.Println("'three' does not exist") // 输出: 'three' does not exist } }
删除元素
使用 delete
函数从 map
中删除元素。
package main import "fmt" func main() { myMap := map[string]int{"one": 1, "two": 2} delete(myMap, "one") fmt.Println(myMap) // 输出:map[two:2] }
3. 遍历 map
使用 for range
语法遍历 map
中的所有键值对。
package main import "fmt" func main() { myMap := map[string]int{"one": 1, "two": 2, "three": 3} for key, value := range myMap { fmt.Printf("Key: %s, Value: %d\n", key, value) } }
4. 注意事项
map
是无序的
map
中的键值对是无序的,每次遍历的顺序可能不同。
零值
map
的零值是 nil
,一个 nil
的 map
不能用于存储键值对,否则会引发运行时错误。
package main import "fmt" func main() { var myMap map[string]int fmt.Println(myMap == nil) // 输出:true // 下面的操作会引发运行时错误:panic: assignment to entry in nil map // myMap["one"] = 1 }
并发访问
map
不是并发安全的。如果需要在多个 goroutine 中并发读写同一个 map
,需要使用同步机制(如 sync.Mutex
或 sync.RWMutex
)来确保安全。
package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup myMap := make(map[string]int) var mu sync.Mutex for i := 0; i < 5; i++ { wg.Add(1) go func(i int) { defer wg.Done() mu.Lock() myMap[fmt.Sprintf("key%d", i)] = i mu.Unlock() }(i) } wg.Wait() fmt.Println(myMap) }
示例代码
下面是一个综合使用 map
的示例代码:
package main import "fmt" func main() { // 创建并初始化 map myMap := map[string]int{"one": 1, "two": 2, "three": 3} // 添加和更新元素 myMap["four"] = 4 myMap["one"] = 10 // 访问元素 value, ok := myMap["two"] if ok { fmt.Println("Value for 'two':", value) } // 删除元素 delete(myMap, "three") // 遍历 map for key, value := range myMap { fmt.Printf("Key: %s, Value: %d\n", key, value) } }