I already know what you’re thinking: No, we don’t need another ORM written in Go.

Very true. Which is why I didn’t write one, promise.

Instead, I wrote tmeta (short for “table meta” or “type meta”, or something). It can parse struct tags to understand how your structs correspond to SQL tables, including common relations (one to many, many to many, etc.), and makes it easy to build corresponding queries:

Focuses solely on understanding type information about your structs and using that to easily build a query.

Structs have SQL table information associated with them - tmeta knows that your WidgetFactory struct corresponds to the “widget_factory” table (names configurable, of course).

struct corresponds to the “widget_factory” table (names configurable, of course). Useful struct tags to express things like primary keys and relations. Sensible defaults but easily configurable.

Relation support (belongs to, has many, has one, belongs to many, belongs to many IDs)

Builds queries using dbr, simple and flexible, avoids the cruft of more complex solutions. Supports common operations like CRUD, loading relations, and maintaining join tables.

Operations are succinct and explicit, not too magical, we’re not trying to be Hiberate (or GORM for that matter); this is Go.

Does not require or expect you to embed a special “Model” type, your structs remain simple, no additional dependencies in your model.

Optimistic locking (version column)

Date Created/Updated functionality

Normal underlying DB features like transactions and context support are not hidden from you and easily usable.

Primary keys can be string/UUID (recommended) or auto-incremented integer.

Does not do DDL, this makes things simpler. (DDL is necessary but should be separate.)

Supports SQLite3, MySQL, Postgres

If you’ve had your share trying to organize a non-trivial Go code base that includes database access, it’s worth a look: https://github.com/gocaveman/tmeta

ORM Woes

There is a whole back story to the research done that lead to tmeta and I hope to write an article on it soon. But the short version is that you can’t write a full-featured Hibernate/JPA-style of ORM in Go due to the way the Go language is organized (there is no DynamicInvocationHandler equivalent). And you can’t emulate what Eloquent or other ORM systems in loosely typed languages do because of Go’s static typing. And more importantly than either of those, even if you could, you wouldn’t want to because you lose the benefits of writing idomatic Go code and introduce a lot of unnecessary complexity.