Golang Tutorial: Generics with Gorm
·1741 words·9 mins·
loading
·
loading
After months and years of talking, trying things out, and testing, we’ve finally reached a big moment in our favorite programming language. The new Golang version, 1.18, is here. We knew it would bring significant changes to Go’s codebase, even before Generics was officially released. For a long time, when we wanted to make our code more general and abstract, we used code generators in Go. Learning what the “Go way” of doing things was challenging for many of us, but it also led to many breakthroughs. It was worth the effort. Now, there are new possibilities on the horizon.
Many new packages have emerged, giving us ideas on how we can improve the Go ecosystem with reusable code that makes life easier for all of us. This inspiration led me to create a small proof of concept using the Gorm library. Now, let’s take a look at it.
Source code # When I wrote this article, it relied on a GitHub Repository. The code served as a Go library proof of concept, with my intention to continue working on it. However, it was not yet suitable for production use, and I had no plans to offer production support at that time.
You can find the current features by following the link, and below, there is a smaller sample snippet.
Example Usage
package main import ( "github.com/ompluscator/gorm-generics" // some imports ) // Product is a domain entity type Product struct { // some fields } // ProductGorm is DTO used to map Product entity to database type ProductGorm struct { // some fields } // ToEntity respects the gorm_generics.GormModel interface func (g ProductGorm) ToEntity() Product { return Product{ // some fields } } // FromEntity respects the gorm_generics.GormModel interface func (g ProductGorm) FromEntity(product Product) interface{} { return ProductGorm{ // some fields } } func main() { db, err := gorm.Open(/* DB connection string */) // handle error err = db.AutoMigrate(ProductGorm{}) // handle error // initialize a new Repository with by providing // GORM model and Entity as type repository := gorm_generics.NewRepository[ProductGorm, Product](db) ctx := context.Background() // create new Entity product := Product{ // some fields } // send new Entity to Repository for storing err = repository.Insert(ctx, &product) // handle error fmt.Println(product) // Out: // {1 product1 100 true} single, err := repository.FindByID(ctx, product.ID) // handle error fmt.Println(single) // Out: // {1 product1 100 true} } Why have I picked ORM for PoC? # Coming from a background in software development with traditional object-oriented programming languages like Java, C#, and PHP, one of the first things I did was search Google for a suitable ORM for Golang. Please forgive my inexperience at the time, but that’s what I was expecting. It’s not that I can’t work without an ORM. It’s just that I don’t particularly like how raw MySQL queries appear in the code. All that string concatenation looks messy to me. On the other hand, I always prefer to dive right into writing business logic, with minimal time spent thinking about the underlying data storage. Sometimes, during the implementation, I change my mind and switch to different types of storage. That’s where ORMs come in handy.