Йосиф обнови решението на 13.11.2014 21:34 (преди над 3 години)
+package main
+
+import "time"
+import "sync"
+import "strconv"
+import "strings"
+
+type SomeError struct {
+ Message string
+}
+
+func (se *SomeError) Error() string {
+ return se.Message
+}
+
+type ExpireMap struct {
+ Cache map[string]interface{}
+ Times map[string]time.Duration
+ Communication chan string
+ Lock *sync.Mutex
+}
+
+func NewExpireMap() *ExpireMap {
+ return &ExpireMap{
+ Cache: make(map[string]interface{}),
+ Times: make(map[string]time.Duration),
+ Communication: make(chan string, 1000),
+ Lock: &sync.Mutex{}}
+}
+
+func (em *ExpireMap) Set(key string, value interface{}, expire time.Duration) {
+ em.Cache[key] = value
+ em.Times[key] = expire
+ go func() {
+ time.Sleep(expire)
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ if _, isPresent := em.Cache[key]; isPresent == true {
+ delete(em.Cache, key)
+ delete(em.Times, key)
+ em.Communication <- key
+ }
+ }()
+}
+
+func (em *ExpireMap) Get(key string) (interface{}, bool) {
+ value, isPresent := em.Cache[key]
+ return value, isPresent
+}
+
+func (em *ExpireMap) GetInt(key string) (int, bool) {
+ value, isPresent := em.Cache[key].(int)
+ if isPresent {
+ return value, isPresent
+ } else {
+ return 0, false
+ }
+}
+
+func (em *ExpireMap) GetFloat64(key string) (float64, bool) {
+ value, isPresent := em.Cache[key].(float64)
+ if isPresent {
+ return value, isPresent
+ } else {
+ return 0, false
+ }
+}
+
+func (em *ExpireMap) GetString(key string) (string, bool) {
+ value, isPresent := em.Cache[key].(string)
+ if isPresent {
+ return value, isPresent
+ } else {
+ return "", false
+ }
+}
+
+func (em *ExpireMap) GetBool(key string) (bool, bool) {
+ value, isPresent := em.Cache[key].(bool)
+ if isPresent {
+ return value, isPresent
+ } else {
+ return false, false
+ }
+}
+
+func (em *ExpireMap) Expires(key string) (time.Time, bool) {
+ timeToLive, isPresent := em.Times[key]
+ if !isPresent {
+ return time.Time{}, false
+ } else {
+ return time.Now().Add(timeToLive), true
+ }
+}
+
+func (em *ExpireMap) Delete(key string) {
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ delete(em.Cache, key)
+ delete(em.Times, key)
+}
+
+func (em *ExpireMap) Contains(key string) bool {
+ _, isPresent := em.Cache[key]
+ return isPresent
+}
+
+func (em *ExpireMap) Size() int {
+ size := 0
+ for _ = range em.Cache {
+ size++
+ }
+ return size
+}
+
+func (em *ExpireMap) Increment(key string) error {
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ if value, isPresent := em.Cache[key]; isPresent == true {
+ switch value_type := value.(type) {
+ case int:
+ em.Cache[key] = value_type + 1
+ return nil
+ case string:
+ if number, err := strconv.Atoi(value_type); err == nil {
+ em.Cache[key] = strconv.Itoa(number + 1)
+ return nil
+ } else {
+ return err
+ }
+ default:
+ return &SomeError{Message: "Unsupported type for this function !"}
+ }
+ }
+ return &SomeError{Message: "No such key"}
+}
+
+func (em *ExpireMap) Decrement(key string) error {
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ if value_type, isPresent := em.Cache[key]; isPresent == true {
+ switch value := value_type.(type) {
+ case int:
+ em.Cache[key] = value - 1
+ return nil
+ case string:
+ if number, err := strconv.Atoi(value); err == nil {
+ em.Cache[key] = strconv.Itoa(number - 1)
+ return nil
+ } else {
+ return err
+ }
+ default:
+ return &SomeError{Message: "Unsupported type for this function !"}
+ }
+ }
+ return &SomeError{Message: "No such key"}
+}
+
+func (em *ExpireMap) ToUpper(key string) error {
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ if value_type, isPresent := em.Cache[key]; isPresent == true {
+ switch value := value_type.(type) {
+ case string:
+ em.Cache[key] = strings.ToUpper(value)
+ return nil
+ default:
+ return &SomeError{Message: "Unsupported value for this function !"}
+ }
+ }
+ return &SomeError{Message: "No such keykey !"}
+}
+
+func (em *ExpireMap) ToLower(key string) error {
+ em.Lock.Lock()
+ defer em.Lock.Unlock()
+
+ if value, isPresent := em.Cache[key]; isPresent == true {
+ switch value_type := value.(type) {
+ case string:
+ em.Cache[key] = strings.ToLower(value_type)
+ return nil
+ default:
+ return &SomeError{Message: "Unsupported type for this function !"}
+ }
+ }
+ return &SomeError{Message: "No such keykey !"}
+}
+
+func (em *ExpireMap) ExpiredChan() <-chan string {
+ channel := make(chan string, 1000)
+ go func() {
+ for {
+ value := <-em.Communication
+ channel <- value
+ }
+ }()
+ return channel
+}
+
+func (em *ExpireMap) Cleanup() {
+ em.Cache = nil
+ em.Times = nil
+ em.Lock = nil
+}
+
+func (em *ExpireMap) Destroy() {
+ em.Cache = nil
+ em.Times = nil
+ em.Lock = nil
+ em = nil
+}