loading...

Interfaces don't need fields

yujiri8 profile image Ryan Westlund ・1 min read

Posting this cause it was something that took me a while to realize, might help other people too.

At one point I thought it was a limitation of Go's type system that you can't define fields in an interface, only methods. But I realized it's not.

You can do that by factoring out the common fields into a substruct, embedding it into the structs that have them, and defining a function that takes that type.

Discussion

markdown guide
 

Would you mind adding a small example?

 

One example that springs to mind for me is modelling data in a database. Let's assume you have Model interface that might look like this,

type Model interface {
    // URL returns the REST endpoint for the current model.
    URL() string

    // Values returns a map of the values in the column for
    // creating and updating the current model.
    Values() map[string]interface{}
}

then you could define a sub-struct like the OP said for abstracting away the common fields that the models in your application might share.

type BaseModel struct {
    ID        int64
    CreatedAt time.Time
    UpdatedAt time.Time
}

This sub-struct could also provide a base implementation for the models that embed it.

func (m *BaseModel) URL() string {
    return fmt.Sprintf("/%v", m.ID)
}

func (m *BaseModel) Values() map[string]interface{} {
    return map[string]interface{}{
        "id":         m.ID,
        "created_at": m.CreatedAt,
        "updated_at": m.UpdatedAt,
    }
}

And an actual model could embed it like so,

type User struct {
    BaseModel

    Username string
    Password []byte
}

I hope this helps provide an example of the whole idea of using a sub-struct to abstract away common fields.