2
votes

I am learning go and was looking at a simple go example web app: https://github.com/campoy/todo/blob/master/task/task.go

Having struct:


    type Task struct {
        ID    int64  // Unique identifier
        Title string // Description
        Done  bool   // Is this task done?
    } 

and


    // TaskManager manages a list of tasks in memory.
    type TaskManager struct {
        tasks  []*Task
        lastID int64
    }

There are methods on the TaskManager func (m *TaskManager) Save(task *Task) error ... func (m *TaskManager) All() []*Task...

I am wondering how to generalize TaskManager into Manager, so it would have these same methods (namely: save, all, find) so it can be used on different structs, for example Users, which would all have ID field.

I assume constructing an array of general type doesn't fit because there is an ID in 'save' and 'find' methods

2

2 Answers

3
votes

Go doesn't have generics (for now, at least), but you still can perform what you want (not 100%) by using an interface.

type Manager interface {
  Save(interface{}) error
  All() ([]interface{}, error)
}

Of course, it doesn't come for free and you need to do some error handling in your TaskManager to implement the interface, example:

func (m *TaskManager) Save(t interface) error {
  task, ok := t.(Task) // type assertion
  if !ok {
    // return error invalid input type
  }
  // do the rest as normal...
}

:Example for comment

type Entry interface {
  SetID(int64)
  GetID()int64
}

type Task struct {...}

func (t *Task) SetID(id int64) {...}
func (t *Task) GetID() {...}

func (m *TaskManager) Save(e Entry) error {...}

More info on interfaces: * http://golang.org/ref/spec#Interface_types
* http://golang.org/doc/effective_go.html#interfaces_and_types
*http://golangtutorials.blogspot.com/2011/06/interfaces-in-go.html

0
votes

You'll probably want to write an interface for structures that have an ID, then generalize your Manager to operate on elements of that interface instead of elements of a specific struct.