package context import "sync" type AttributeManager interface { Init() SetAttribute(key string, value interface{}) GetAttribute(key string) (value interface{}) RemoveAttribute(key string) Contains(key string) (exist bool) Destroy() } type AttributeManagers struct { Parent AttributeManager attributes map[string]interface{} mtx sync.RWMutex } func (am *AttributeManagers) Init() { if nil != am.Parent { am.Parent.Init() } if nil == am.attributes { am.Destroy() } am.attributes = make(map[string]interface{}) } func (am *AttributeManagers) SetAttribute(key string, value interface{}) { am.checkInitialized() am.mtx.Lock() defer am.mtx.Unlock() am.attributes[key] = value } func (am *AttributeManagers) GetAttribute(key string) (value interface{}) { am.checkInitialized() am.mtx.RLock() defer am.mtx.RUnlock() if _, ok := am.attributes[key]; ok { return am.attributes[key] } if nil == am.Parent { return nil } return am.Parent.GetAttribute(key) } func (am *AttributeManagers) RemoveAttribute(key string) { am.checkInitialized() am.mtx.Lock() defer am.mtx.Unlock() if _, ok := am.attributes[key]; ok { delete(am.attributes, key) return } if nil == am.Parent { return } am.Parent.RemoveAttribute(key) } func (am *AttributeManagers) Contains(key string) (exist bool) { am.checkInitialized() am.mtx.RLock() defer am.mtx.RUnlock() if _, ok := am.attributes[key]; ok { return true } if nil == am.Parent { return false } return am.Parent.Contains(key) } func (am *AttributeManagers) Destroy() { if nil != am.attributes { am.attributes = nil } if nil != am.Parent { am.Parent.Destroy() } } func (am *AttributeManagers) checkInitialized() { if nil == am.attributes { panic("Attribute Manager: must be initialized") } }