#Go Maps
A map is an associative array in Go used to store key-value pairs. It provides fast lookup, insertion, and deletion operations, making it an important data structure for building efficient programs.
#📋 Map Basics
#Map Declaration and Initialization
package main
import "fmt"
func main() {
// 1. 声明映射(零值为 nil)
var m1 map[string]int
fmt.Printf("零值映射: %v, 是否为nil: %t\n", m1, m1 == nil)
// 2. 使用 make 创建映射
m2 := make(map[string]int)
fmt.Printf("make映射: %v, 长度: %d\n", m2, len(m2))
// 3. 映射字面量初始化
m3 := map[string]int{
"apple": 5,
"banana": 3,
"orange": 8,
}
fmt.Printf("字面量映射: %v, 长度: %d\n", m3, len(m3))
// 4. 空映射初始化
m4 := map[string]int{}
fmt.Printf("空映射: %v, 长度: %d\n", m4, len(m4))
// 5. 不同类型的映射
ages := map[string]int{
"Alice": 25,
"Bob": 30,
"Carol": 28,
}
scores := map[int]float64{
1001: 95.5,
1002: 87.3,
1003: 92.1,
}
fmt.Printf("年龄映射: %v\n", ages)
fmt.Printf("分数映射: %v\n", scores)
}#Map Operations
func main() {
// 创建映射
fruits := make(map[string]int)
// 添加元素
fruits["apple"] = 10
fruits["banana"] = 5
fruits["orange"] = 8
fmt.Printf("初始映射: %v\n", fruits)
// 访问元素
appleCount := fruits["apple"]
fmt.Printf("苹果数量: %d\n", appleCount)
// 修改元素
fruits["apple"] = 15
fmt.Printf("修改后: %v\n", fruits)
// 检查键是否存在
count, exists := fruits["grape"]
if exists {
fmt.Printf("葡萄数量: %d\n", count)
} else {
fmt.Printf("葡萄不存在,返回零值: %d\n", count)
}
// 添加新元素
fruits["grape"] = 12
fmt.Printf("添加葡萄后: %v\n", fruits)
// 删除元素
delete(fruits, "banana")
fmt.Printf("删除香蕉后: %v\n", fruits)
// 映射长度
fmt.Printf("映射长度: %d\n", len(fruits))
}#🔍 Iterating Over Maps
#Iterating Key-Value Pairs
func main() {
studentGrades := map[string]float64{
"Alice": 95.5,
"Bob": 87.3,
"Carol": 92.1,
"David": 78.9,
"Eve": 88.7,
}
fmt.Println("遍历所有键值对:")
for name, grade := range studentGrades {
fmt.Printf("学生: %s, 成绩: %.1f\n", name, grade)
}
fmt.Println("\n只遍历键:")
for name := range studentGrades {
fmt.Printf("学生: %s\n", name)
}
fmt.Println("\n只遍历值:")
for _, grade := range studentGrades {
fmt.Printf("成绩: %.1f\n", grade)
}
// 注意:映射的遍历顺序是随机的
fmt.Println("\n多次遍历展示随机顺序:")
for i := 0; i < 3; i++ {
fmt.Printf("第%d次遍历: ", i+1)
for name := range studentGrades {
fmt.Printf("%s ", name)
}
fmt.Println()
}
}#Ordered Iteration
import (
"fmt"
"sort"
)
func main() {
data := map[string]int{
"charlie": 3,
"alice": 1,
"bob": 2,
"dave": 4,
}
fmt.Printf("原始映射: %v\n", data)
// 按键排序遍历
var keys []string
for key := range data {
keys = append(keys, key)
}
sort.Strings(keys)
fmt.Println("按键排序遍历:")
for _, key := range keys {
fmt.Printf("%s: %d\n", key, data[key])
}
// 按值排序遍历
type KeyValue struct {
Key string
Value int
}
var kvPairs []KeyValue
for key, value := range data {
kvPairs = append(kvPairs, KeyValue{key, value})
}
// 按值排序
sort.Slice(kvPairs, func(i, j int) bool {
return kvPairs[i].Value < kvPairs[j].Value
})
fmt.Println("按值排序遍历:")
for _, kv := range kvPairs {
fmt.Printf("%s: %d\n", kv.Key, kv.Value)
}
}#🔧 Advanced Map Operations
#Maps of Maps
func main() {
// 嵌套映射:学生的各科成绩
studentScores := map[string]map[string]float64{
"Alice": {
"Math": 95.0,
"English": 88.5,
"Science": 92.3,
},
"Bob": {
"Math": 87.5,
"English": 91.2,
"Science": 89.8,
},
}
fmt.Println("学生成绩:")
for student, scores := range studentScores {
fmt.Printf("%s的成绩:\n", student)
for subject, score := range scores {
fmt.Printf(" %s: %.1f\n", subject, score)
}
}
// 添加新学生
studentScores["Carol"] = make(map[string]float64)
studentScores["Carol"]["Math"] = 93.7
studentScores["Carol"]["English"] = 89.4
studentScores["Carol"]["Science"] = 95.1
// 修改成绩
studentScores["Alice"]["Math"] = 97.0
// 安全访问嵌套映射
if aliceScores, exists := studentScores["Alice"]; exists {
if mathScore, hasMatch := aliceScores["Math"]; hasMatch {
fmt.Printf("Alice的数学成绩: %.1f\n", mathScore)
}
}
// 计算平均分
for student, scores := range studentScores {
total := 0.0
count := 0
for _, score := range scores {
total += score
count++
}
average := total / float64(count)
fmt.Printf("%s的平均分: %.2f\n", student, average)
}
}#Maps as Sets
func main() {
// 使用映射实现集合功能
set1 := make(map[string]bool)
set2 := make(map[string]bool)
// 添加元素到集合
fruits1 := []string{"apple", "banana", "orange", "grape"}
fruits2 := []string{"banana", "orange", "kiwi", "mango"}
for _, fruit := range fruits1 {
set1[fruit] = true
}
for _, fruit := range fruits2 {
set2[fruit] = true
}
fmt.Printf("集合1: %v\n", getKeys(set1))
fmt.Printf("集合2: %v\n", getKeys(set2))
// 交集
intersection := make(map[string]bool)
for key := range set1 {
if set2[key] {
intersection[key] = true
}
}
fmt.Printf("交集: %v\n", getKeys(intersection))
// 并集
union := make(map[string]bool)
for key := range set1 {
union[key] = true
}
for key := range set2 {
union[key] = true
}
fmt.Printf("并集: %v\n", getKeys(union))
// 差集 (set1 - set2)
difference := make(map[string]bool)
for key := range set1 {
if !set2[key] {
difference[key] = true
}
}
fmt.Printf("差集(1-2): %v\n", getKeys(difference))
}
// 获取映射的所有键
func getKeys(m map[string]bool) []string {
keys := make([]string, 0, len(m))
for key := range m {
keys = append(keys, key)
}
return keys
}#Map Copying and Comparison
func main() {
original := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
// 浅复制
shallowCopy := original
fmt.Printf("原始映射: %v\n", original)
fmt.Printf("浅复制: %v\n", shallowCopy)
// 修改浅复制会影响原始映射
shallowCopy["d"] = 4
fmt.Printf("修改浅复制后:\n")
fmt.Printf("原始映射: %v\n", original)
fmt.Printf("浅复制: %v\n", shallowCopy)
// 深复制
deepCopy := make(map[string]int)
for key, value := range original {
deepCopy[key] = value
}
fmt.Printf("深复制: %v\n", deepCopy)
// 修改深复制不会影响原始映射
deepCopy["e"] = 5
fmt.Printf("修改深复制后:\n")
fmt.Printf("原始映射: %v\n", original)
fmt.Printf("深复制: %v\n", deepCopy)
// 映射比较(只能与 nil 比较)
var nilMap map[string]int
fmt.Printf("原始映射是否为nil: %t\n", original == nil)
fmt.Printf("nil映射是否为nil: %t\n", nilMap == nil)
// 自定义映射比较函数
map1 := map[string]int{"a": 1, "b": 2}
map2 := map[string]int{"a": 1, "b": 2}
map3 := map[string]int{"a": 1, "b": 3}
fmt.Printf("map1 == map2: %t\n", compareMaps(map1, map2))
fmt.Printf("map1 == map3: %t\n", compareMaps(map1, map3))
}
// 自定义映射比较函数
func compareMaps(m1, m2 map[string]int) bool {
if len(m1) != len(m2) {
return false
}
for key, value1 := range m1 {
if value2, exists := m2[key]; !exists || value1 != value2 {
return false
}
}
return true
}#🎯 Practical Examples
#Word Counter
import (
"fmt"
"regexp"
"sort"
"strings"
)
type WordCounter struct {
words map[string]int
total int
}
func NewWordCounter() *WordCounter {
return &WordCounter{
words: make(map[string]int),
total: 0,
}
}
func (wc *WordCounter) AddText(text string) {
// 转换为小写并提取单词
text = strings.ToLower(text)
reg := regexp.MustCompile(`[a-z]+`)
words := reg.FindAllString(text, -1)
for _, word := range words {
wc.words[word]++
wc.total++
}
}
func (wc *WordCounter) GetWordCount(word string) int {
return wc.words[strings.ToLower(word)]
}
func (wc *WordCounter) GetTotalWords() int {
return wc.total
}
func (wc *WordCounter) GetUniqueWords() int {
return len(wc.words)
}
func (wc *WordCounter) GetTopWords(n int) []struct {
Word string
Count int
} {
type WordCount struct {
Word string
Count int
}
var wordCounts []WordCount
for word, count := range wc.words {
wordCounts = append(wordCounts, WordCount{word, count})
}
// 按计数排序
sort.Slice(wordCounts, func(i, j int) bool {
return wordCounts[i].Count > wordCounts[j].Count
})
if n > len(wordCounts) {
n = len(wordCounts)
}
return wordCounts[:n]
}
func (wc *WordCounter) GetWordFrequency(word string) float64 {
count := wc.GetWordCount(word)
if wc.total == 0 {
return 0
}
return float64(count) / float64(wc.total) * 100
}
func main() {
counter := NewWordCounter()
// 添加文本
texts := []string{
"Go is a programming language developed by Google.",
"Go is simple, fast, and reliable.",
"Programming in Go is fun and productive.",
"Google created Go for modern software development.",
}
for _, text := range texts {
counter.AddText(text)
}
// 统计结果
fmt.Printf("总词数: %d\n", counter.GetTotalWords())
fmt.Printf("唯一词数: %d\n", counter.GetUniqueWords())
// 查询特定单词
queryWords := []string{"go", "programming", "google", "python"}
fmt.Println("\n单词查询:")
for _, word := range queryWords {
count := counter.GetWordCount(word)
frequency := counter.GetWordFrequency(word)
fmt.Printf("%s: 出现%d次, 频率%.2f%%\n", word, count, frequency)
}
// 高频词汇
fmt.Println("\n前5个高频词汇:")
topWords := counter.GetTopWords(5)
for i, wc := range topWords {
fmt.Printf("%d. %s: %d次\n", i+1, wc.Word, wc.Count)
}
}#Cache System
import (
"fmt"
"sync"
"time"
)
// 缓存项
type CacheItem struct {
Value interface{}
Expiration time.Time
}
// 检查是否过期
func (item CacheItem) IsExpired() bool {
return time.Now().After(item.Expiration)
}
// 简单缓存系统
type SimpleCache struct {
items map[string]CacheItem
mutex sync.RWMutex
}
func NewSimpleCache() *SimpleCache {
cache := &SimpleCache{
items: make(map[string]CacheItem),
}
// 启动清理过期项的 goroutine
go cache.cleanupExpired()
return cache
}
// 设置缓存项
func (c *SimpleCache) Set(key string, value interface{}, duration time.Duration) {
c.mutex.Lock()
defer c.mutex.Unlock()
expiration := time.Now().Add(duration)
c.items[key] = CacheItem{
Value: value,
Expiration: expiration,
}
}
// 获取缓存项
func (c *SimpleCache) Get(key string) (interface{}, bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()
item, exists := c.items[key]
if !exists {
return nil, false
}
if item.IsExpired() {
delete(c.items, key)
return nil, false
}
return item.Value, true
}
// 删除缓存项
func (c *SimpleCache) Delete(key string) {
c.mutex.Lock()
defer c.mutex.Unlock()
delete(c.items, key)
}
// 获取缓存大小
func (c *SimpleCache) Size() int {
c.mutex.RLock()
defer c.mutex.RUnlock()
return len(c.items)
}
// 清空缓存
func (c *SimpleCache) Clear() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.items = make(map[string]CacheItem)
}
// 获取所有键
func (c *SimpleCache) Keys() []string {
c.mutex.RLock()
defer c.mutex.RUnlock()
keys := make([]string, 0, len(c.items))
for key, item := range c.items {
if !item.IsExpired() {
keys = append(keys, key)
}
}
return keys
}
// 清理过期项
func (c *SimpleCache) cleanupExpired() {
ticker := time.NewTicker(1 * time.Minute)
defer ticker.Stop()
for range ticker.C {
c.mutex.Lock()
for key, item := range c.items {
if item.IsExpired() {
delete(c.items, key)
}
}
c.mutex.Unlock()
}
}
func main() {
cache := NewSimpleCache()
// 设置缓存项
cache.Set("user:1001", "Alice", 5*time.Second)
cache.Set("user:1002", "Bob", 10*time.Second)
cache.Set("config:timeout", 30, 1*time.Minute)
fmt.Printf("缓存大小: %d\n", cache.Size())
fmt.Printf("所有键: %v\n", cache.Keys())
// 获取缓存项
if value, exists := cache.Get("user:1001"); exists {
fmt.Printf("用户1001: %v\n", value)
}
if value, exists := cache.Get("config:timeout"); exists {
fmt.Printf("超时配置: %v\n", value)
}
// 等待一些项过期
fmt.Println("等待5秒...")
time.Sleep(6 * time.Second)
fmt.Printf("5秒后缓存大小: %d\n", cache.Size())
fmt.Printf("5秒后所有键: %v\n", cache.Keys())
// 再次获取过期的项
if value, exists := cache.Get("user:1001"); exists {
fmt.Printf("用户1001: %v\n", value)
} else {
fmt.Println("用户1001已过期")
}
if value, exists := cache.Get("user:1002"); exists {
fmt.Printf("用户1002: %v\n", value)
} else {
fmt.Println("用户1002已过期")
}
}#🎓 Summary
In this chapter, we comprehensively learned about Go maps:
- ✅ Map basics: declaration, initialization, basic operations
- ✅ Map iteration: random iteration, ordered iteration
- ✅ Advanced operations: nested maps, maps as sets
- ✅ Practical applications: word counter, cache system
Maps are an important data structure in Go. Mastering their use is essential for building efficient programs.
Next, we will learn about Go Interfaces to understand Go's polymorphism and abstraction mechanisms.
::: tip Map Usage Tips
- Maps are not thread-safe; concurrent access requires locking
- Map iteration order is random; do not rely on ordering
- Use the
value, ok := map[key]syntax to check if a key exists - Consider memory usage when working with large amounts of data :::