Map实战 #
一、计数器模式 #
1.1 单词计数 #
go
func wordCount(text string) map[string]int {
words := strings.Fields(text)
counts := make(map[string]int)
for _, word := range words {
counts[strings.ToLower(word)]++
}
return counts
}
text := "hello world hello go world"
fmt.Println(wordCount(text))
// map[hello:2 world:2 go:1]
1.2 字符频率统计 #
go
func charFrequency(s string) map[rune]int {
freq := make(map[rune]int)
for _, r := range s {
freq[r]++
}
return freq
}
1.3 投票计数 #
go
type VoteCounter struct {
counts map[string]int
mu sync.RWMutex
}
func NewVoteCounter() *VoteCounter {
return &VoteCounter{
counts: make(map[string]int),
}
}
func (vc *VoteCounter) Vote(candidate string) {
vc.mu.Lock()
defer vc.mu.Unlock()
vc.counts[candidate]++
}
func (vc *VoteCounter) GetCount(candidate string) int {
vc.mu.RLock()
defer vc.mu.RUnlock()
return vc.counts[candidate]
}
func (vc *VoteCounter) GetResults() map[string]int {
vc.mu.RLock()
defer vc.mu.RUnlock()
result := make(map[string]int)
for k, v := range vc.counts {
result[k] = v
}
return result
}
二、缓存模式 #
2.1 简单缓存 #
go
type Cache struct {
data map[string]interface{}
mu sync.RWMutex
}
func NewCache() *Cache {
return &Cache{
data: make(map[string]interface{}),
}
}
func (c *Cache) Get(key string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
v, ok := c.data[key]
return v, ok
}
func (c *Cache) Set(key string, value interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
func (c *Cache) Delete(key string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.data, key)
}
2.2 带过期时间的缓存 #
go
type CacheItem struct {
Value interface{}
Expiration time.Time
}
type TTLCache struct {
data map[string]CacheItem
mu sync.RWMutex
}
func (c *TTLCache) Get(key string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
item, ok := c.data[key]
if !ok {
return nil, false
}
if time.Now().After(item.Expiration) {
return nil, false
}
return item.Value, true
}
func (c *TTLCache) Set(key string, value interface{}, ttl time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = CacheItem{
Value: value,
Expiration: time.Now().Add(ttl),
}
}
三、分组模式 #
3.1 按字段分组 #
go
type Person struct {
Name string
City string
Age int
}
func groupByCity(people []Person) map[string][]Person {
groups := make(map[string][]Person)
for _, p := range people {
groups[p.City] = append(groups[p.City], p)
}
return groups
}
3.2 通用分组函数 #
go
func GroupBy[T any, K comparable](items []T, keyFunc func(T) K) map[K][]T {
groups := make(map[K][]T)
for _, item := range items {
key := keyFunc(item)
groups[key] = append(groups[key], item)
}
return groups
}
people := []Person{
{"Alice", "Beijing", 25},
{"Bob", "Shanghai", 30},
{"Carol", "Beijing", 28},
}
groups := GroupBy(people, func(p Person) string {
return p.City
})
四、索引模式 #
4.1 ID索引 #
go
type User struct {
ID int
Name string
}
func buildUserIndex(users []User) map[int]User {
index := make(map[int]User)
for _, u := range users {
index[u.ID] = u
}
return index
}
func findUser(index map[int]User, id int) (User, bool) {
u, ok := index[id]
return u, ok
}
4.2 多字段索引 #
go
type UserDB struct {
byID map[int]*User
byName map[string]*User
mu sync.RWMutex
}
func NewUserDB() *UserDB {
return &UserDB{
byID: make(map[int]*User),
byName: make(map[string]*User),
}
}
func (db *UserDB) Add(u *User) {
db.mu.Lock()
defer db.mu.Unlock()
db.byID[u.ID] = u
db.byName[u.Name] = u
}
func (db *UserDB) FindByID(id int) (*User, bool) {
db.mu.RLock()
defer db.mu.RUnlock()
u, ok := db.byID[id]
return u, ok
}
func (db *UserDB) FindByName(name string) (*User, bool) {
db.mu.RLock()
defer db.mu.RUnlock()
u, ok := db.byName[name]
return u, ok
}
五、集合模式 #
5.1 使用Map实现集合 #
go
type Set map[string]struct{}
func NewSet(items ...string) Set {
s := make(Set)
for _, item := range items {
s[item] = struct{}{}
}
return s
}
func (s Set) Add(item string) {
s[item] = struct{}{}
}
func (s Set) Remove(item string) {
delete(s, item)
}
func (s Set) Contains(item string) bool {
_, ok := s[item]
return ok
}
func (s Set) ToSlice() []string {
result := make([]string, 0, len(s))
for item := range s {
result = append(result, item)
}
return result
}
5.2 集合运算 #
go
func Union(s1, s2 Set) Set {
result := make(Set)
for k := range s1 {
result[k] = struct{}{}
}
for k := range s2 {
result[k] = struct{}{}
}
return result
}
func Intersection(s1, s2 Set) Set {
result := make(Set)
for k := range s1 {
if s2.Contains(k) {
result[k] = struct{}{}
}
}
return result
}
func Difference(s1, s2 Set) Set {
result := make(Set)
for k := range s1 {
if !s2.Contains(k) {
result[k] = struct{}{}
}
}
return result
}
六、配置管理 #
6.1 配置存储 #
go
type Config struct {
data map[string]interface{}
mu sync.RWMutex
}
func NewConfig() *Config {
return &Config{
data: make(map[string]interface{}),
}
}
func (c *Config) GetString(key string) string {
c.mu.RLock()
defer c.mu.RUnlock()
if v, ok := c.data[key]; ok {
return v.(string)
}
return ""
}
func (c *Config) GetInt(key string) int {
c.mu.RLock()
defer c.mu.RUnlock()
if v, ok := c.data[key]; ok {
return v.(int)
}
return 0
}
func (c *Config) Set(key string, value interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
}
七、总结 #
Map实战要点:
| 模式 | 应用场景 |
|---|---|
| 计数器 | 统计频率、投票 |
| 缓存 | 数据缓存、结果缓存 |
| 分组 | 数据分类 |
| 索引 | 快速查找 |
| 集合 | 去重、集合运算 |
关键点:
- 并发安全:使用sync.RWMutex保护Map
- 性能优化:预分配容量
- 内存管理:及时清理不需要的数据
- 类型安全:使用泛型提高类型安全
准备好学习字符串了吗?让我们进入下一章!
最后更新:2026-03-26