Go(Golang)的ORM:GORM、Ent和sqlx对比及示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Go (Golang) 的 ORM:比较与示例



在使用 Go (Golang) 开发时,数据库操作是一项关键任务。与许多动态语言不同,Go 没有内置的 ORM(对象关系映射),但社区创建了几个强大的库。在本文中,我们将详细比较三种流行的方法:GORM、Ent 和 sqlx。您将了解它们的优缺点,并看到每个库的代码示例。



为什么 Go 需要 ORM?



ORM 简化了与关系型数据库的交互,允许将表作为普通的 Go 结构体进行操作。主要优势包括:

  • 自动生成 SQL 查询
  • 数据库模式迁移
  • 防止 SQL 注入
  • 加速开发


然而,ORM 在处理复杂查询时可能会降低性能,并隐藏 SQL 细节,这对于高负载项目来说至关重要。



1. GORM — Go 中最流行的 ORM



GORM 是一个功能齐全的 ORM,拥有活跃的社区(GitHub 上超过 35k 星)。它提供了丰富的 API,用于 CRUD 操作、迁移、钩子和关系处理。



GORM 使用示例



定义模型并执行简单操作:



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") }

// 自动迁移 db.AutoMigrate(&User{})

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

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

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

// 删除 db.Delete(&user)}


GORM 的优点:

  • 简单直观的 API
  • 支持关系(BelongsTo、HasMany、Many2Many)
  • 内置迁移和钩子
  • 广泛支持数据库(PostgreSQL、MySQL、SQLite、SQL Server)


缺点:

  • 复杂查询时性能下降
  • 魔法行为(例如自动修改字段)
  • 自定义 SQL 查询较为困难


2. Ent — Facebook 的 code-first ORM



Ent 是一个基于代码生成的 ORM。与 GORM 使用反射不同,Ent 从模式生成类型安全的 Go 代码,从而提供高性能和类型安全。



Ent 使用示例



首先在 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(), }}


生成代码后(使用命令 go generate ./...),使用生成的 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()

// 自动迁移 if err := client.Schema.Create(ctx); err != nil { log.Fatal(err) }

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

推荐