func (c *MemoryCache) Remove(key string) {
	c.mu.Lock()
	c.removeNoLock(key)
	c.mu.Unlock()
}
Remove removes an entry from the cache
package main
import (
	"crypto/md5"
	"fmt"
	"regexp"
	"strings"
	"sync"
	"time"
	"github.com/miekg/dns"
	"github.com/ryanuber/go-glob"
)
const globChars = "*?"
type KeyNotFound struct {
	key string
}
func (e KeyNotFound) Error() string {
	return e.key + " " + "not found"
}
type KeyExpired struct {
	Key string
}
func (e KeyExpired) Error() string {
	return e.Key + " " + "expired"
}
type CacheIsFull struct {
}
func (e CacheIsFull) Error() string {
	return "Cache is Full"
}
type Mesg struct {
	Msg            *dns.Msg
	Blocked        bool
	LastUpdateTime time.Time
}
type Cache interface {
	Get(key string) (Msg *dns.Msg, blocked bool, err error)
	Set(key string, Msg *dns.Msg, blocked bool) error
	Exists(key string) bool
	Remove(key string)
	Length() int
}
type MemoryCache struct {
	Backend  map[string]*Mesg
	Maxcount int
	mu       sync.RWMutex
}
type MemoryBlockCache struct {
	Backend map[string]bool
	Special map[string]*regexp.Regexp
	mu      sync.RWMutex
}
type MemoryQuestionCache struct {
	Backend  []QuestionCacheEntry `json:"entry"`
	Maxcount int
	mu       sync.RWMutex
}
func (c *MemoryCache) Get(key string) (*dns.Msg, bool, error) {
	key = strings.ToLower(key)
	now := WallClock.Now().Truncate(time.Second)
	expired := false
	c.mu.Lock()
	mesg, ok := c.Backend[key]
	if ok && mesg.Msg == nil {
		ok = false
		logger.Warningf("Cache: key %s returned nil entry", key)
		c.removeNoLock(key)
	}
	if ok {
		elapsed := uint32(now.Sub(mesg.LastUpdateTime).Seconds())
		for _, answer := range mesg.Msg.Answer {
			if elapsed > answer.Header().Ttl {
				logger.Debugf("Cache: Key expired %s", key)
				c.removeNoLock(key)
				expired = true
			}
			answer.Header().Ttl -= elapsed
		}
	}
	c.mu.Unlock()
	if !ok {
		logger.Debugf("Cache: Cannot find key %s\n", key)
		return nil, false, KeyNotFound{key}
	}
	if expired {
		return nil, false, KeyExpired{key}
	}
	mesg.LastUpdateTime = now
	return mesg.Msg, mesg.Blocked, nil
}
func (c *MemoryCache) Set(key string, msg *dns.Msg, blocked bool) error {
	key = strings.ToLower(key)
	if c.Full() && !c.Exists(key) {
		return CacheIsFull{}
	}
	if msg == nil {
		logger.Debugf("Setting an empty value for key %s", key)
	}
	c.mu.Lock()
	c.Backend[key] = &Mesg{msg, blocked, WallClock.Now().Truncate(time.Second)}
	c.mu.Unlock()
	return nil
}
func (c *MemoryCache) removeNoLock(key string) {
	key = strings.ToLower(key)
	delete(c.Backend, key)
}