ORM for Go (Golang): comparison and usage 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



Development in Go (Golang) often requires interaction with databases. Instead of writing raw SQL queries, developers increasingly turn to ORM (Object-Relational Mapping) — tools that automate the conversion of data between a relational database and language objects. In this article, we will cover the four most popular ORMs for Go: GORM, Ent, SQLBoiler, and Bun. You will learn their strengths and weaknesses, see code examples, and be able to make an informed choice for your project.



Why do you need an ORM in Go?

An ORM solves several key tasks:

  • Reducing boilerplate code — no need to write CRUD operations manually.
  • Type safety — the Go compiler checks that struct fields match table columns.
  • Schema migrations — automatic creation and updating of tables.
  • Database abstraction — switching DBMS (PostgreSQL, MySQL, SQLite) without rewriting queries.


1. GORM — the most popular choice

GORM is the de facto standard ORM in the Go ecosystem. It is known for its rich functionality: automatic migrations, hooks, method chaining, support for transactions and relationships (Has Many, Belongs To, Many2Many).



GORM code example

package main

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

type User struct { gorm.Model 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{})

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

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

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

// Delete db.Delete(&user)}


Pros: huge community, extensive documentation, built-in support for associations and hooks.

Cons: sometimes slow performance on complex queries, magical behavior (e.g., automatic field modification).



2. Ent — code generation and strict typing

Ent from Facebook (Meta) is not just an ORM, but a whole framework for working with entities. It generates Go code based on a schema described in Go syntax. This provides maximum performance and type safety.



Ent code example

// schema/user.gopackage 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(), }}

// main.gopackage main

import ( "context" "log"

"entgo.io/ent/dialect/sqlite" "yourproject/ent")

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

ctx := context.Background() // Create tables if err := client.Schema.Create(ctx); err != nil { log.Fatal(err) }

// Insert u, _ := client.User.Create().SetName("Alice").SetEmail("alice@example.com").Save(ctx)

// Read user, _ := client.User.Get(ctx, u.ID) log.Println(user.Name)}


Pros: high performance, full typing, excellent support for graph queries.

Cons: steep learning curve, need to run code generation, fewer built-in features (e.g., no hooks).



3. SQLBoiler —

Recommendations