ORM for Go (Golang): comparison of GORM, Ent and sqlx with examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

ORM for Go (Golang): comparison and examples



When developing in Go (Golang), working with databases is one of the key tasks. Unlike many dynamic languages, Go does not have a built-in ORM (Object-Relational Mapping), but the community has created several powerful libraries. In this article, we will compare three popular approaches in detail: GORM, Ent, and sqlx. You will learn their strengths and weaknesses, and see code examples for each library.



Why do you need an ORM in Go?



An ORM simplifies interaction with relational databases by allowing you to work with tables as regular Go structs. The main advantages are:

  • Automatic generation of SQL queries
  • Database schema migrations
  • Protection against SQL injections
  • Faster development


However, an ORM can reduce performance on complex queries and hide SQL details, which is critical for high-load projects.



1. GORM — the most popular ORM for Go



GORM is a full-featured ORM with an active community (over 35k stars on GitHub). It provides a rich API for CRUD operations, migrations, hooks, and relationships.



Example of working with GORM



Let's define a model and perform simple operations:



package main

import ( "gorm.io/driver/sqlite" "gorm.io/gorm")

type User struct { ID uint `gorm:"primaryKey"` Name string Email string `gorm:"uniqueIndex"`}

func main() { db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) if err != nil { panic("failed to connect database") }

// Auto-migration db.AutoMigrate(&User{})

// Create db.Create(&User{Name: "Alice", Email: "alice@example.com"})

// Read var user User db.First(&user, 1) // by ID db.First(&user, "email = ?", "alice@example.com")

// Update db.Model(&user).Update("Name", "Alice Updated")

// Delete db.Delete(&user)}


Pros of GORM:

  • Simple and intuitive API
  • Support for relationships (BelongsTo, HasMany, Many2Many)
  • Built-in migrations and hooks
  • Wide support for DBMS (PostgreSQL, MySQL, SQLite, SQL Server)


Cons:

  • Performance degradation on complex queries
  • Magical behavior (e.g., automatic field modification)
  • Difficulties with custom SQL queries


2. Ent — code-first ORM from Facebook



Ent is an ORM based on code generation. Instead of reflection, as in GORM, Ent generates typed Go code from a schema, which provides high performance and type safety.



Example of working with Ent



First, let's define a schema in the file schema/user.go:



package schema

import ( "entgo.io/ent" "entgo.io/ent/schema/field")

type User struct { ent.Schema}

func (User) Fields() []ent.Field { return []ent.Field{ field.String("name"), field.String("email").Unique(), }}


After code generation (command go generate ./...), we use the generated API:



package main

import ( "context" "log"

"your-project/ent" _ "github.com/mattn/go-sqlite3")

func main() { client, err := ent.Open("sqlite3", "file:ent.db?cache=shared&_fk=1") if err != nil { log.Fatal(err) } defer client.Close()

ctx := context.Background()

// Auto-migration if err := client.Schema.Create(ctx); err != nil { log.Fatal(err) }

// Create user user, err := client.User.Create(). SetName("Bob"). SetEmail("bob@example.com"). Save(ctx) if err != ni

Recommendations