了解go版本的数据库工具

举报
码乐 发表于 2024/09/15 08:00:01 2024/09/15
【摘要】 1 简介工具ent、gorm 和 goqu 是 Go 语言中常用的 ORM 和查询生成器工具。它们的优缺点和属性对比如下:ent优点:类型安全: ent 提供了基于代码生成的强类型 API,可以在编译时捕获更多的错误。Schema 设计: 使用 GraphQL 风格的 schema 定义,清晰且易于理解和维护。强大的查询生成: 通过链式调用构建查询,提供了灵活且强大的查询生成器。迁移管理:...

1 简介工具

ent、gorm 和 goqu 是 Go 语言中常用的 ORM 和查询生成器工具。它们的优缺点和属性对比如下:

  • ent

优点:

类型安全: ent 提供了基于代码生成的强类型 API,可以在编译时捕获更多的错误。
Schema 设计: 使用 GraphQL 风格的 schema 定义,清晰且易于理解和维护。
强大的查询生成: 通过链式调用构建查询,提供了灵活且强大的查询生成器。
迁移管理: 内置迁移工具,支持自动和手动迁移。
扩展性: 通过钩子和中间件机制,可以轻松扩展和定制。

缺点:

学习曲线: 对于初学者来说,理解和使用 ent 可能比 gorm 更复杂。
开发速度: 由于依赖代码生成,可能在开发初期稍慢。
社区和生态: 相较于 gorm,ent 的社区和生态系统相对较小。

  • gorm

优点:

易于使用: 语法简单直观,上手快。
功能全面: 支持包括查询、迁移、钩子、关联等在内的丰富功能。
社区和生态: 拥有庞大的社区和丰富的第三方插件。
性能: 经过多年的发展和优化,gorm 的性能稳定且高效。

缺点:

类型安全性较低: 由于是基于反射的 ORM,在编译时无法捕获类型错误,容易出现运行时错误。
复杂查询: 对于复杂查询的支持不如 ent 那么友好和强大。
灵活性: 虽然功能全面,但在一些场景下,可能不如 ent 那么灵活和可扩展。

  • goqu

优点:

SQL 生成器: goqu 是一个强大的 SQL 生成器,支持复杂查询生成。
灵活性: 由于是 SQL 生成器,可以与任何数据库驱动兼容,不局限于 ORM 框架。
类型安全: 提供了类型安全的查询生成器,可以在编译时捕获错误。
轻量级: 比起完整的 ORM 框架,goqu 更加轻量级,适用于需要手动控制 SQL 生成的场景。

缺点:

迁移支持: goqu 不直接提供迁移工具,需要依赖其他工具。
学习曲线: 对于习惯了 ORM 框架的用户来说,goqu 的使用方式可能需要一些适应。
社区和生态: 相较于 gorm,goqu 的社区和生态系统相对较小。

2 属性对比

数据库支持:

ent: 支持 SQLite、MySQL、PostgreSQL 等。
gorm: 支持 SQLite、MySQL、PostgreSQL、SQL Server 等。
goqu: 支持 SQLite、MySQL、PostgreSQL、SQL Server 等。

迁移管理:

ent: 内置迁移工具,支持自动和手动迁移。
gorm: 通过 gormigrate 或 goose 等第三方工具支持迁移。
goqu: 不直接提供迁移工具,需要使用 goose 或其他工具。

查询语句生成:

ent: 强类型的链式查询生成,编译时类型检查。
gorm: 通过链式调用和反射实现查询生成。
goqu: 强类型的 SQL 查询生成器,支持复杂查询。

钩子和中间件:

ent: 支持在创建、更新、删除等操作前后定义钩子。
gorm: 提供丰富的钩子支持,可以在不同生命周期阶段插入逻辑。
goqu: 不直接提供钩子机制,但可以在应用层面实现。

3 示例代码

以下是 ent、gorm 和 goqu 的示例代码,展示了如何在 MySQL 中进行简单的 CRUD 操作:

  • ent 示例

      package main
    
      import (
          "context"
          "log"
    
          "entgo.io/ent/dialect"
          _ "github.com/go-sql-driver/mysql"
          "entgo.io/ent/dialect/sql"
          "myapp/ent"
      )
    
      func main() {
          client, err := ent.Open(dialect.MySQL, "user:password@tcp(localhost:3306)/dbname?parseTime=True")
          if err != nil {
              log.Fatalf("failed opening connection to mysql: %v", err)
          }
          defer client.Close()
    
          if err := client.Schema.Create(context.Background()); err != nil {
              log.Fatalf("failed creating schema resources: %v", err)
          }
    
          user, err := client.User.Create().SetName("John").Save(context.Background())
          if err != nil {
              log.Fatalf("failed creating user: %v", err)
          }
          log.Printf("user created: %v", user)
      }
    
  • gorm 示例

      package main
    
      import (
          "gorm.io/driver/mysql"
          "gorm.io/gorm"
          "log"
      )
    
      type User struct {
          ID   uint   `gorm:"primaryKey"`
          Name string `gorm:"size:255"`
      }
    
      func main() {
          dsn := "user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
          db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
          if err != nil {
              log.Fatalf("failed to connect database: %v", err)
          }
    
          if err := db.AutoMigrate(&User{}); err != nil {
              log.Fatalf("failed to migrate database: %v", err)
          }
    
          user := User{Name: "John"}
          if err := db.Create(&user).Error; err != nil {
              log.Fatalf("failed to create user: %v", err)
          }
          log.Printf("user created: %v", user)
      }
    
  • goqu 示例

      package main
    
      import (
          "database/sql"
          "log"
    
          "github.com/doug-martin/goqu/v9"
          _ "github.com/go-sql-driver/mysql"
      )
    
      type User struct {
          ID   uint   `db:"id"`
          Name string `db:"name"`
      }
    
      func main() {
          db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname?parseTime=true")
          if err != nil {
              log.Fatal(err)
          }
          defer db.Close()
    
          goquDB := goqu.New("mysql", db)
    
          insert := goquDB.Insert("users").Rows(
              goqu.Record{"name": "John"},
          ).Executor()
    
          if _, err := insert.Exec(); err != nil {
              log.Fatalf("failed to insert user: %v", err)
          }
    
          var user User
          found, err := goquDB.From("users").Where(goqu.Ex{"name": "John"}).ScanStruct(&user)
          if err != nil {
              log.Fatalf("failed to get user: %v", err)
          }
          if !found {
              log.Printf("user not found")
          } else {
              log.Printf("user found: %v", user)
          }
      }
    

5 总结

ent 适合需要强类型、灵活查询生成和内置迁移支持的项目,适合对类型安全要求高的开发者。
gorm 适合希望快速上手、使用简单且功能全面的项目,适合需要大量社区支持和插件的开发者。
goqu 适合需要灵活生成 SQL 查询、手动控制查询生成且不需要完整 ORM 框架的项目,适合对 SQL 有深入了解的开发者。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。