package main import "errors" type LockedCredentialManager interface { Unlock(masterKey string) (UnlockedCredentialManager, error) } type UnlockedCredentialManager interface { Lock() (LockedCredentialManager, error) Set(key string, secret string) error Get(key string) (string, error) } type credentialManager struct { unlocked bool entries map[string]string } func NewCredentialManager() LockedCredentialManager { return &credentialManager{ entries: make(map[string]string), } } func (t *credentialManager) Unlock(masterKey string) (UnlockedCredentialManager, error) { if t.unlocked { return nil, errors.New("already unlocked") } t.unlocked = true return t, nil } func (t *credentialManager) Lock() (LockedCredentialManager, error) { if !t.unlocked { return nil, errors.New("already locked") } t.unlocked = false return t, nil } func (t *credentialManager) Set(key string, secret string) error { if !t.unlocked { return errors.New("locked") } panic("todo") } func (t *credentialManager) Get(key string) (string, error) { if !t.unlocked { return "", errors.New("locked") } panic("todo") } func main() { pwLocked := NewCredentialManager() pwUnlocked, _ := pwLocked.Unlock("pssst") pwUnlocked.Set("foo", "bar") _, _ = pwUnlocked.Get("foo") pwUnlocked.Lock() }