Golang的GORM vs. Ent对比,你更会用哪个?

开发 前端
Ent 是由 Facebook 开发的一个 Go ORM 库,旨在提供强类型的、基于代码生成的数据库访问。Ent 侧重于代码生成,借助代码生成工具生成实体、查询构建器和数据库迁移代码,避免了手写 SQL 或构建复杂的查询。

在 Go 语言的 ORM(Object-Relational Mapping)库中,GORM 和 Ent 是两个非常流行的选择。它们都为 Go 提供了高效的数据库操作和对象映射功能,但在设计理念、功能特点、使用方式以及性能方面有所不同。下面我们将通过对比两者的特性,帮助你了解哪个框架更适合你的项目需求。

1. 概述

  • GORM

a.GORM 是一个流行的 Go ORM 库,广泛应用于 Go 项目中。它的特点是易于使用和灵活,支持常见的数据库操作,如创建、读取、更新和删除(CRUD),并且提供了丰富的功能,诸如关联查询、事务、自动迁移等。

b.GORM 采用基于结构体的方式进行模型定义,并通过标签(tags)定义表结构和字段。

  • Ent
  • Ent 是由 Facebook 开发的一个 Go ORM 库,旨在提供强类型的、基于代码生成的数据库访问。Ent 侧重于代码生成,借助代码生成工具生成实体、查询构建器和数据库迁移代码,避免了手写 SQL 或构建复杂的查询。
  • Ent 更加注重类型安全和高效的查询构建,适合大型项目和复杂数据库架构。

2. 主要差异

图片

3. 代码示例对比

3.1 GORM 示例

假设我们有一个简单的 UserProfile 之间的一对一关系:

package main

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

type User struct {
	ID      uint
	Name    string
	Profile Profile
}

type Profile struct {
	ID     uint
	UserID uint
	Age    int
}

func main() {
	// 初始化数据库连接
	db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

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

	// 创建数据
	user := User{Name: "John", Profile: Profile{Age: 30}}
	db.Create(&user)

	// 查询并关联
	var result User
	db.Preload("Profile").First(&result, "name = ?", "John")
	fmt.Println(result)
}

特点:

  • 使用 gorm 标签自动映射数据库表。
  • 使用 Preload 来加载关联的 Profile 数据。
  • 自动迁移功能,快速构建数据库。

3.2 Ent 示例

假设我们有一个类似的 UserProfile 模型:

首先,定义 schema 文件(user.goprofile.go)。

ent/schema/user.go

package schema

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

// User holds the schema definition for the User entity.
type User struct {
	ent.Schema
}

// Fields of the User.
func (User) Fields() []ent.Field {
	return []ent.Field{
		field.String("name").
			NotEmpty(),
	}
}

// Edges of the User.
func (User) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("profile", Profile.Type).
			Unique(),
	}
}

ent/schema/profile.go

package schema

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

// Profile holds the schema definition for the Profile entity.
type Profile struct {
	ent.Schema
}

// Fields of the Profile.
func (Profile) Fields() []ent.Field {
	return []ent.Field{
		field.Int("age").
			Positive(),
	}
}

// Edges of the Profile.
func (Profile) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("user", User.Type).
			Ref("profile").
			Unique(),
	}
}

接下来,通过 ent 工具生成代码:

go run entgo.io/ent/cmd/ent generate ./ent/schema

然后,你可以像下面这样使用生成的代码:

package main

import (
	"context"
	"fmt"
	"log"

	"entgo.io/ent/dialect/sql"
	_ "github.com/mattn/go-sqlite3"
	"myapp/ent"
)

func main() {
	client, err := ent.Open(sqlite.Open("ent.db"), &ent.Config{})
	if err != nil {
		log.Fatal("Failed to connect to database:", err)
	}
	defer client.Close()

	// 执行迁移
	if err := client.Schema.Create(context.Background()); err != nil {
		log.Fatal("Failed to create schema:", err)
	}

	// 创建 User 和 Profile
	user, err := client.User.
		Create().
		SetName("John").
		SetProfileAge(30).
		Save(context.Background())
	if err != nil {
		log.Fatal("Failed to create user:", err)
	}

	// 查询 User 并预加载 Profile
	result, err := client.User.Query().
		Where(user.Name("John")).
		WithProfile().
		Only(context.Background())
	if err != nil {
		log.Fatal("Failed to query user:", err)
	}

	// 输出结果
	fmt.Println("User:", result)
}

特点:

  • 使用 Ent schema 来定义数据模型和关联关系。
  • 使用 生成的代码 来进行查询和数据操作(通过构建器模式)。
  • 需要生成代码,且对数据库操作有强类型的保障。

4. 对比总结

图片

5. 选择建议

  • 选择 GORM:如果你需要一个快速、灵活的 ORM,支持丰富的功能,并且在项目中不需要特别复杂的类型安全或生成代码的机制,GORM 是一个很好的选择。它有着非常活跃的社区和大量的文档资源,适合小到中型项目。
  • 选择 Ent:如果你对类型安全和性能有更高的要求,或者项目比较大,需要一个强类型的查询构建器,Ent 是一个更适合的选择。Ent 可以帮助你更好地组织代码,尤其是在复杂数据库和多表关联的场景下。它适合大型、复杂的项目,尤其是当你的团队更注重代码生成和类型安全时。

6. 总结

  • GORM 更适合需要快速开发和灵活操作的项目,尤其是中小型项目。
  • Ent 更适合对类型安全、性能和可维护性要求较高的项目,尤其是大型系统。
责任编辑:武晓燕 来源: Go语言圈
相关推荐

2024-04-03 08:28:31

GolangPHP语言

2017-06-27 15:08:05

大数据Apache SparKafka Strea

2020-04-15 10:21:43

云计算AWSAzure

2021-01-13 16:04:07

网络On-Prem托管

2015-09-16 11:29:46

超融合架构软件定义存储

2022-01-25 19:36:46

ChromeBrave浏览器

2022-01-26 10:26:57

ChromeBrave网页浏览器

2016-05-31 11:00:43

数据中心数据中心硬件数据中心搭建

2023-11-23 13:10:24

Python框架

2014-09-28 10:29:43

乔布斯施密特Android

2021-12-23 15:36:21

NASSANDAS

2024-09-12 22:45:47

2023-05-22 19:49:30

命令Linux

2020-08-25 09:14:17

对象存储文件存储块存储

2019-04-02 15:07:51

API NginxZuul

2024-03-19 08:36:19

2017-07-25 14:45:32

GlusterFSCeph存储

2024-12-13 08:12:02

2023-07-11 17:50:04

操作系统Ubuntu

2023-12-05 15:18:27

事件驱动架构RESTful通信模式
点赞
收藏

51CTO技术栈公众号