An empty interface is a Go interface type with no method requirements. A value of type interface{} can therefore hold a task.Task, task.TaskEvent, or another type, helping a manager depend on a storage contract instead of a built-in map. section 11.2
Using an empty interface shifts type checking to the store implementation:
- Put accepts an arbitrary value, then uses a type assertion to require a pointer to task.Task before storing it. section 11.3
- Get returns interface{}; callers use a type assertion to convert the result back to *task.Task and handle failures. section 11.3 section 11.5
- List returns an interface{} containing a slice of tasks, which the manager converts to []*task.Task. section 11.3 section 11.5
A typed boundary around flexible storage
type Store interface { Put(key string, value interface{}) error Get(key string) (interface{}, error) List() (interface{}, error) Count() (int, error) } func (i *InMemoryTaskStore) Put(key string, value interface{}) error { t, ok := value.(*task.Task) if !ok { return fmt.Errorf("value is not a task.Task type") } i.Db[key] = t return nil }
Listing 11.2 The Store interface
type Store interface {
Put(key string, value interface{}) error
Get(key string) (interface{}, error)
List() (interface{}, error)
Count() (int, error)
}
Inspect the Store interface to see where empty-interface values make storage implementations interchangeable. section 11.2



