Skip to content

simple cache.go

文件信息

  • 📄 原文件:03_simple_cache.go
  • 🔤 语言:go

完整代码

go
package main

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

// ============================================================
//                      小项目3:简单缓存
// ============================================================
// 功能:内存缓存,支持过期时间
// 知识点:map、互斥锁、goroutine、time

// CacheItem 缓存项
type CacheItem struct {
	Value      interface{}
	Expiration int64 // Unix 时间戳,0 表示永不过期
}

// IsExpired 是否已过期
func (item CacheItem) IsExpired() bool {
	if item.Expiration == 0 {
		return false
	}
	return time.Now().UnixNano() > item.Expiration
}

// Cache 缓存
type Cache struct {
	items map[string]CacheItem
	mu    sync.RWMutex
}

// NewCache 创建缓存
func NewCache() *Cache {
	c := &Cache{
		items: make(map[string]CacheItem),
	}

	// 启动清理 goroutine
	go c.cleanupLoop()

	return c
}

// Set 设置缓存(带过期时间)
func (c *Cache) Set(key string, value interface{}, ttl time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()

	var expiration int64
	if ttl > 0 {
		expiration = time.Now().Add(ttl).UnixNano()
	}

	c.items[key] = CacheItem{
		Value:      value,
		Expiration: expiration,
	}
}

// Get 获取缓存
func (c *Cache) Get(key string) (interface{}, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()

	item, found := c.items[key]
	if !found {
		return nil, false
	}

	if item.IsExpired() {
		return nil, false
	}

	return item.Value, true
}

// Delete 删除缓存
func (c *Cache) Delete(key string) {
	c.mu.Lock()
	defer c.mu.Unlock()

	delete(c.items, key)
}

// Clear 清空缓存
func (c *Cache) Clear() {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.items = make(map[string]CacheItem)
}

// Count 缓存数量
func (c *Cache) Count() int {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return len(c.items)
}

// Keys 所有键
func (c *Cache) Keys() []string {
	c.mu.RLock()
	defer c.mu.RUnlock()

	keys := make([]string, 0, len(c.items))
	for k := range c.items {
		keys = append(keys, k)
	}
	return keys
}

// cleanupLoop 定期清理过期项
func (c *Cache) cleanupLoop() {
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for range ticker.C {
		c.deleteExpired()
	}
}

// deleteExpired 删除过期项
func (c *Cache) deleteExpired() {
	c.mu.Lock()
	defer c.mu.Unlock()

	now := time.Now().UnixNano()
	for k, v := range c.items {
		if v.Expiration > 0 && now > v.Expiration {
			delete(c.items, k)
		}
	}
}

// runSimpleCache 运行缓存示例
func runSimpleCache() {
	fmt.Println("\n=== 小项目3: 简单缓存 ===")

	cache := NewCache()

	// 设置缓存
	cache.Set("name", "张三", 0)                    // 永不过期
	cache.Set("token", "abc123", 2*time.Second)     // 2秒后过期
	cache.Set("data", map[string]int{"a": 1}, 0)

	fmt.Println("--- 设置缓存 ---")
	fmt.Println("缓存数量:", cache.Count())
	fmt.Println("所有键:", cache.Keys())

	// 获取缓存
	fmt.Println("\n--- 获取缓存 ---")
	if name, ok := cache.Get("name"); ok {
		fmt.Println("name:", name)
	}

	if token, ok := cache.Get("token"); ok {
		fmt.Println("token:", token)
	}

	if data, ok := cache.Get("data"); ok {
		fmt.Println("data:", data)
	}

	// 等待过期
	fmt.Println("\n--- 等待 3 秒... ---")
	time.Sleep(3 * time.Second)

	fmt.Println("--- 过期后 ---")
	if _, ok := cache.Get("name"); ok {
		fmt.Println("name: 仍存在")
	}

	if _, ok := cache.Get("token"); ok {
		fmt.Println("token: 仍存在")
	} else {
		fmt.Println("token: 已过期")
	}

	// 删除缓存
	cache.Delete("name")
	fmt.Println("\n删除 'name' 后,缓存数量:", cache.Count())

	// 清空缓存
	cache.Clear()
	fmt.Println("清空后,缓存数量:", cache.Count())
}

// ============================================================
//                      小项目3b:并发安全计数器
// ============================================================

// Counter 并发安全计数器
type Counter struct {
	mu    sync.Mutex
	value int
}

// Increment 增加
func (c *Counter) Increment() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.value++
}

// Decrement 减少
func (c *Counter) Decrement() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.value--
}

// Value 获取值
func (c *Counter) Value() int {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.value
}

func runConcurrentCounter() {
	fmt.Println("\n=== 并发安全计数器 ===")

	counter := &Counter{}
	var wg sync.WaitGroup

	// 启动 100 个 goroutine 增加计数
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < 100; j++ {
				counter.Increment()
			}
		}()
	}

	wg.Wait()
	fmt.Println("100 个 goroutine 各增加 100 次,最终值:", counter.Value())
}

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布