A sentinel error is a predefined, unique error value representing a known condition. Packages commonly expose these values with names beginning with Err, allowing callers to make consistent programmatic decisions instead of matching message strings. section 7.7 section 7.8
Use sentinel errors when a caller needs to recognize a recurring condition:
- Define package-level values such as ErrConflict and ErrNotExist. section 7.7
- Return the same value whenever the corresponding condition occurs. section 7.7
- Check with errors.Is so handling remains valid through wrapped errors. section 7.8
- Add a custom error type when the failure also needs variable data, such as missing keys. section 7.9
A key-value store
A KVStore can return ErrConflict when Put encounters an existing key and ErrNotExist when Get or Delete cannot find one. ForcePut uses errors.Is(err, ErrConflict) to delete the old value and retry, while wrapped errors preserve the underlying cause. section 7.7 section 7.8
Listing 7.10 main.go: Sentinel errors
type KVStore struct {
m map[string]string
}
func NewKVStore() *KVStore {
m := make(map[string]string)
return &KVStore{
m: m,
}
}
var ( #1
ErrConflict error = errors.New("key already exists") #2
ErrNotExist error = errors.New("no value exists for key")
)
Inspect the package-level ErrConflict and ErrNotExist definitions used by the KVStore example. section 7.7
Listing 7.12 main.go: Using errors.Is to check for sentinel errors
type Store interface {
...
ForcePut(key string, val string) error
}
...
func (store *KVStore) ForcePut(key string, val string) error {
err := store.Put(key, val)
if err == nil {
return nil
}
if errors.Is(err, ErrConflict) { #1
if err := store.Delete(key); err != nil {
return errors.New("unable to delete as part of force put") #2
}
if err := store.Put(key, val); err != nil {
return errors.New("unable to delete as part of force put)
}
return nil
}
return errors.New("unable to force put, unknown error")
}
Inspect ForcePut handling a conflict with errors.Is and a conditional retry. section 7.8


