内存键值对存储


场景  验证码

package base64Captcha
// Store An object implementing Store interface can be registered with SetCustomStore // function to handle storage and retrieval of captcha ids and solutions for // them, replacing the default memory store. // // It is the responsibility of an object to delete expired and used captchas // when necessary (for example, the default memory store collects them in Set // method after the certain amount of captchas has been stored.) type Store interface {     // Set sets the digits for the captcha id.     Set(id string, value string) error
    // Get returns stored digits for the captcha id. Clear indicates     // whether the captcha must be deleted from the store.     Get(id string, clear bool) string
    //Verify captcha's answer directly     Verify(id, answer string, clear bool) bool }

github.com\mojocn\base64!captcha@v1.3.5\interface_store.go

github.com\mojocn\base64!captcha@v1.3.5\store_memory.go

package base64Captcha import (     "container/list"     "sync"     "time" ) // expValue stores timestamp and id of captchas. It is used in the list inside // memoryStore for indexing generated captchas by timestamp to enable garbage // collection of expired captchas. type idByTimeValue struct {     timestamp time.Time     id        string } // memoryStore is an internal store for captcha ids and their values. type memoryStore struct {     sync.RWMutex     digitsById map[string]string     idByTime   *list.List     // Number of items stored since last collection.     numStored int     // Number of saved items that triggers collection.     collectNum int     // Expiration time of captchas.     expiration time.Duration } // NewMemoryStore returns a new standard memory store for captchas with the // given collection threshold and expiration time (duration). The returned // store must be registered with SetCustomStore to replace the default one. func NewMemoryStore(collectNum int, expiration time.Duration) Store {     s := new(memoryStore)     s.digitsById = make(map[string]string)     s.idByTime = list.New()     s.collectNum = collectNum     s.expiration = expiration     return s } func (s *memoryStore) Set(id string, value string) error {     s.Lock()     s.digitsById[id] = value     s.idByTime.PushBack(idByTimeValue{time.Now(), id})     s.numStored++     s.Unlock()     if s.numStored > s.collectNum {         go s.collect()     }     return nil } func (s *memoryStore) Verify(id, answer string, clear bool) bool {     v := s.Get(id, clear)     return v == answer } func (s *memoryStore) Get(id string, clear bool) (value string) {     if !clear {         // When we don't need to clear captcha, acquire read lock.         s.RLock()         defer s.RUnlock()     } else {         s.Lock()         defer s.Unlock()     }     value, ok := s.digitsById[id]     if !ok {         return     }     if clear {         delete(s.digitsById, id)     }     return } func (s *memoryStore) collect() {     now := time.Now()     s.Lock()     defer s.Unlock()     for e := s.idByTime.Front(); e != nil; {         e = s.collectOne(e, now)     } } func (s *memoryStore) collectOne(e *list.Element, specifyTime time.Time) *list.Element {     ev, ok := e.Value.(idByTimeValue)     if !ok {         return nil     }     if ev.timestamp.Add(s.expiration).Before(specifyTime) {         delete(s.digitsById, ev.id)         next := e.Next()         s.idByTime.Remove(e)         s.numStored--         return next     }     return nil }

Go进阶37:重构我的base64Captcha图形验证码项目 | ?????? https://mojotv.cn/go/refactor-base64-captcha