You don’t need orm in Go

ℹ️ This article is based on Go 1.18.

Object-relational mapping (ORM) is a technique (a.k.a. design pattern) of accessing a relational database from an object-oriented language (Java, for example). There are multiple implementations of ORM in almost every language; for example: Hibernate for Java, ActiveRecord for Ruby on Rails, Doctrine for PHP, and SQLAlchemy for Python.

Of course, there is also libraries for Go like gorm or xorm. These libraries are huge and they use a lot reflection package and one of the Go proverbs is reflection is never clear. Some people argue that the ORM is anti pattern and here you can read more about it. ORM can help but on complex queries I like more SQL if I need more dependency just to include ORM I will not do it. On other side we have db libraries which can help to

There are many well-written and tested DB libraries for Go that can help with faster development and cleaner code. But wait! There is a very powerful standard library included in Go that can do most of your daily work just by using it. When I started programming in Go, everyone said that the language was framework agnostic and there was no need for unnecessary dependencies. IMHO a good project structure and architecture should rely on a standard lib and a few infrastructure dependencies (db, message broker etc.). In the following example I would like to show how easy it is to have DB calls without a framework or library. Because it uses generics, we can only try these examples on Go 1.18+ this functions are reflection free.

First we just need simple interface for querying data with provided context.

Query function is very basic one, probably you wrote same code many times and this function is just different because it uses generics and binder function for type T.

Example: List all persons and bind data to slice of type T from db

Query function can be even more simplified. Instead of attaching binder on every call we can decorate Query with Scanner interface for binding data to T type. T must implement interface with just one basic method Scan.

QueryScan decorates Query function with scan method implemented on type T and returns slice of T

Person struct implements Scanner interface and Scan method returns slice of pointers of Person fields.

Go generics is still in early stage but in few next releases probably should expect many new features.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store