flyfei

映射(Map)

1. 语法讲解

映射是一种内置数据结构,用于存储键值对的无序集合。映射是引用类型,传递开销小。

// 映射声明与初始化
var m1 map[string]int           // 声明nil映射
m2 := make(map[string]int)      // 使用make创建
m3 := map[string]int{           // 字面量创建
    "apple":  5,
    "banana": 10,
}

// 操作
m2["apple"] = 5          // 插入或更新
value := m2["apple"]     // 查找
delete(m2, "apple")      // 删除
value, exists := m2["apple"] // 检查键是否存在

并发安全问题Go的map在并发读写时不是线程安全的,需要配合sync包中的锁机制;或者使用sync.Map

2. 应用场景

3. 编程实例

用户会话管理

package main

import (
    "fmt"
    "sync"
    "time"
)

type UserSession struct {
    UserID    string
    LoginTime time.Time
    LastActivity time.Time
    IPAddress string
}

type SessionManager struct {
    sessions map[string]*UserSession
    mutex    sync.RWMutex // 解决并发安全问题
}

func NewSessionManager() *SessionManager {
    return &SessionManager{
        sessions: make(map[string]*UserSession),
    }
}

func (sm *SessionManager) AddSession(token string, userID, ip string) {
    sm.mutex.Lock()
    defer sm.mutex.Unlock()
    
    sm.sessions[token] = &UserSession{
        UserID:       userID,
        LoginTime:    time.Now(),
        LastActivity: time.Now(),
        IPAddress:    ip,
    }
}

func (sm *SessionManager) GetSession(token string) (*UserSession, bool) {
    sm.mutex.RLock()
    defer sm.mutex.RUnlock()
    
    session, exists := sm.sessions[token]
    if exists {
        session.LastActivity = time.Now() // 更新最后活动时间
    }
    return session, exists
}

func (sm *SessionManager) RemoveSession(token string) {
    sm.mutex.Lock()
    defer sm.mutex.Unlock()
    
    delete(sm.sessions, token)
}

func (sm *SessionManager) CleanupExpiredSessions(timeout time.Duration) {
    sm.mutex.Lock()
    defer sm.mutex.Unlock()
    
    now := time.Now()
    for token, session := range sm.sessions {
        if now.Sub(session.LastActivity) > timeout {
            delete(sm.sessions, token)
        }
    }
}

func main() {
    sessionManager := NewSessionManager()
    
    // 模拟用户登录
    sessionManager.AddSession("token123", "user456", "192.168.1.100")
    
    // 验证会话
    if session, exists := sessionManager.GetSession("token123"); exists {
        fmt.Printf("找到用户会话: %s, 登录时间: %v\n", 
            session.UserID, session.LoginTime.Format("2006-01-02 15:04:05"))
    }
    
    // 定期清理过期会话
    sessionManager.CleanupExpiredSessions(30 * time.Minute)
}

4. 其他用法

package main

import "fmt"

func main() {
    // 1. 嵌套map
    userPreferences := map[string]map[string]interface{}{
        "user1": {
            "theme":    "dark",
            "language": "zh-CN",
            "notifications": map[string]bool{
                "email": true,
                "sms":   false,
            },
        },
    }
    
    // 2. 作为集合使用
    uniqueIDs := make(map[int]bool)
    ids := []int{1, 2, 2, 3, 4, 4, 5}
    for _, id := range ids {
        uniqueIDs[id] = true
    }
    fmt.Printf("唯一ID数量: %d\n", len(uniqueIDs))
    
    // 3. 键值反转
    originalMap := map[string]int{
        "A": 1,
        "B": 2,
        "C": 3,
    }
    invertedMap := make(map[int]string)
    for k, v := range originalMap {
        invertedMap[v] = k
    }
    
    // 4. 有序遍历(通过额外切片)
    import "sort"
    
    ageMap := map[string]int{
        "Alice": 25,
        "Bob":   30,
        "Carol": 28,
    }
    
    // 提取键并排序
    keys := make([]string, 0, len(ageMap))
    for k := range ageMap {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    
    // 按排序后的键遍历
    for _, k := range keys {
        fmt.Printf("%s: %d\n", k, ageMap[k])
    }
    
    //声明sync.Map
    var syncmap sync.Map
    syncmap.Store("zhangsan", 97)
    syncmap.Store("lisi", 100)
    syncmap.Store("wangmazi", 200)

    // Load方法获取sync.Map 键所对应的值
    fmt.Println(syncmap.Load("lisi"))

    // Delete方法键删除对应的键值对
    syncmap.Delete("lisi")
    
    // Range遍历所有sync.Map中的键值对
    syncmap.Range(func(k, v interface{}) bool {
        fmt.Println(k, v)
        return true
    })
}

5. 课时总结