Basic API in golang antipattern?

In Go, interfaces are behavioural. That is, they describe what a thing does more than what it is. Your example looks like you’re trying to write C# in Go, with your heavy use of I in front of interface classes. However, an interface that is only implemented by one type is a bit of a waste of time.

Instead, consider:

interface Deleteable {  // You'd probably be tempted to call this IDeleteable
                        // Effective go suggests Deleter, but the grammar 
                        // sounds weird
    Delete() err
}

Now you can create a function to perform batch deletes:

func BatchDelete(victims []Deleteable) {
    // Do some cool things for batching, connect to db, start a transaction
    for _, victim := range(victims) {
        victim.Delete()  // Or arrange for this function to be called somehow.
    }
}

You’d probably get started faster by creating an interface for Update, Serialize and so on, and storing your actual users/permissions/etc in concrete structs that implement those methods. (Note in Go you don’t have to say that a type implements an interface, it happens “automatically”). You also don’t have to have a single interface for each method (Updater, Serializable), but you can bundle them all into one interface:

type DBObject interface {
    Update()
    Serialize() RowType
    Delete()
}

type User struct {
    Id int
    Name string
    // ... etc
}

Remember, your model can always “Fill in” a User object to return from your API, even if the actual representation of the User object is something much more diffuse, e.g. RDF triples.

Leave a Comment