Go语言之Gorm框架(一) ——初窥Gorm框架

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: Go语言之Gorm框架(一) ——初窥Gorm框架

Gorm和Mysql驱动的安装

打开终端,输入下列命令即可:

go get gorm.io/driver/mysql
go get gorm.io/gorm

Gorm连接数据库

示例

package main
import (
  "fmt"
  "github.com/sirupsen/logrus"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
func init() {
  //数据库连接信息
  username := "root"
  password := "123456"
  databasename := "gorm"
  localHost := "localhost"
  port := 3306
  dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
    username, password, localHost, port, databasename)
  db, err := gorm.Open(mysql.Open(dns))
  if err != nil {
    logrus.Error("数据库连接失败", err)
  }
  fmt.Println("数据库连接成功", db)
}
func main() {
}

数据库连接的细节

  • 跳过默认事务
    为了保证数据一致性,Gorm会在事务中去执行去执行增删查改,如果我们没有这个需求可以选择跳过默认事务:
db, err := gorm.Open(mysql.Open(dns),&gorm.Config{SkipDefaultTransaction: true})
  • 命名策略
    在grom中默认表名是复数,字段是单数,比如下面我们创建一张student表,代码是这样的:
package main
import (
  "fmt"
  "github.com/sirupsen/logrus"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
var dB *gorm.DB
type Student struct {
  Name string
  Age  int
  Sex  string
}
func init() {
  //数据库连接信息
  username := "root"
  password := "ba161754"
  databasename := "gorm"
  localHost := "localhost"
  port := 3306
  dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
    username, password, localHost, port, databasename)
  db, err := gorm.Open(mysql.Open(dns), &gorm.Config{SkipDefaultTransaction: true})
  if err != nil {
    logrus.Error("数据库连接失败", err)
  }
  dB = db
}
func main() {
  err := dB.AutoMigrate(Student{})
  if err != nil {
    logrus.Error("数据库迁移失败", err)
  }
  fmt.Println("创建表成功")
}

创建出来的表是这样的:

当然我们也可以尝试修改这种命名策略:

db, err := gorm.Open(mysql.Open(dns), &gorm.Config{SkipDefaultTransaction: true,
    NamingStrategy: schema.NamingStrategy{   //
      TablePrefix:   "t_",  //表名前缀
      SingularTable: false, //禁用表名复数
      NoLowerCase:   false, //禁用小写
    }})
  • 日志显示
func initLogger() {
  var mysqlLogger logger.Interface
  mysqlLogger = logger.Default.LogMode(logger.Info) //设置日志打印级别
  mysqlLogger = logger.New(
    log.New(os.Stdout, "\r\n", log.LstdFlags), // (日志输出的目标,前缀和日志包含的内容)
    logger.Config{
      SlowThreshold:             time.Second, // 慢 SQL 阈值
      LogLevel:                  logger.Info, // 日志级别
      IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound(记录未找到)错误
      Colorful:                  true,        // 使用彩色打印
    },
  )
  dB.Logger = mysqlLogger
}

完整代码,仅供参考:

package main
import (
  "fmt"
  "github.com/sirupsen/logrus"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
  "gorm.io/gorm/logger"
  "gorm.io/gorm/schema"
  "log"
  "os"
  "time"
)
var dB *gorm.DB
type Student struct {
  Name string
  Age  int
  Sex  string
}
func ConnectDB() {
  //数据库连接信息
  username := "root"
  password := "ba161754"
  databasename := "gorm"
  localHost := "localhost"
  port := 3306
  var err error
  dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
    username, password, localHost, port, databasename)
  dB, err = gorm.Open(mysql.Open(dns), &gorm.Config{SkipDefaultTransaction: true,
    NamingStrategy: schema.NamingStrategy{ //
      TablePrefix:   "t_",  //表名前缀
      SingularTable: false, //禁用表名复数
      NoLowerCase:   false, //禁用小写
    }})
  if err != nil {
    logrus.Error("数据库连接失败", err)
  }
}
func initLogger() {
  var mysqlLogger logger.Interface
  mysqlLogger = logger.Default.LogMode(logger.Info) //设置日志打印级别
  mysqlLogger = logger.New(
    log.New(os.Stdout, "\r\n", log.LstdFlags), // (日志输出的目标,前缀和日志包含的内容)
    logger.Config{
      SlowThreshold:             time.Second, // 慢 SQL 阈值
      LogLevel:                  logger.Info, // 日志级别
      IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound(记录未找到)错误
      Colorful:                  true,        // 使用彩色打印
    },
  )
  dB.Logger = mysqlLogger
}
func init() {
  ConnectDB()
  initLogger()
}
func main() {
  err := dB.AutoMigrate(Student{})
  if err != nil {
    logrus.Error("数据库迁移失败", err)
  }
  fmt.Println("创建表成功")
}

模型定义

模型定义示例

模型是使用普通结构体定义的。 这些结构体可以包含具有基本Go类型、指针或这些类型的别名,甚至是自定义类型(只需要实现 database/sql 包中的Scanner和Valuer接口)我们来看一下Gorm给出的user模型示例:

type User struct {
  ID           uint           // Standard field for the primary key
  Name         string         // 一个常规字符串字段
  Email        *string        // 一个指向字符串的指针, allowing for null values
  Age          uint8          // 一个未签名的8位整数
  Birthday     *time.Time     // A pointer to time.Time, can be null
  MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
  ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
  CreatedAt    time.Time      // 创建时间(由GORM自动管理)
  UpdatedAt    time.Time      // 最后一次更新时间(由GORM自动管理)
}

这里常见的uint这种类型就不做过多介绍了,这里主要是 有两个类型我们这里进行一下介绍:

  • *string(指针类型) :如果我们在这里使用string类型的话,这里我们是可以写空值的,如果我们用string类型是不允许出现空值的
  • sql.NullString sql.NullString 是 Go 语言标准库中的一个数据类型,位于 database/sql 包中。它用于表示数据库中可能为 NULL 的字符串值。它由两个字段组成:String 用于保存字符串值(如果不为 NULL),Valid 是一个布尔标志,指示字符串值是否为 NULL。在与允许字符串列包含 NULL 值的数据库一起工作时,这种类型特别有用。
type NullString struct {
  String string
  Valid  bool // Valid is true if String is not NULL
}

gorm.Model

在开始介绍gorm.Model之前,我们先讲一下几条在gorm的约定:

-主键:GORM 使用一个名为ID 的字段作为每个模型的默认主键。

  • 表名:默认情况下,GORM 将结构体名称转换为 snake_case 并为表名加上复数形式。 例如,一个 User 结构体在数据库中的表名变为 users 。
  • 列名:GORM 自动将结构体字段名称转换为 snake_case 作为数据库中的列名。
  • 时间戳字段:GORM使用字段 CreatedAt 和 UpdatedAt 来自动跟踪记录的创建和更新时间。

而在grom中存在gorm.Model这一预定义的结构体,我们可以将它直接嵌入我们所定义的结构体中,这保证了不同模型之间保持一致性并利用GORM内置的约定,gorm.model的定义如下:

type Model struct {
  ID        uint `gorm:"primarykey"` 
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt DeletedAt `gorm:"index"`
}

它主要包含以下字段:

  • ID :每个记录的唯一标识符(主键)。
  • CreatedAt :在创建记录时自动设置为当前时间。
  • UpdatedAt:每当记录更新时,自动更新为当前时间。
  • DeletedAt:用于软删除(将记录标记为已删除,而实际上并未从数据库中删除)。

字段标签

gorm中我们一般使用字段标签来表示字段的类型,常见的字段类型主要有以下几种:

  • type:定义字段类型
  • size:字段大小
  • column 自定义别名
  • primaryKey 将列定义为主键
  • unique 将列定义为唯一键
  • default 定义列的默认值
  • not null 不可为空
  • embedded 嵌套字段
  • embeddedPrefix 嵌套字段前缀
  • comment 注释

示例:

type StudentInfo struct {
 Email  *string `gorm:"size:32"` // 使用指针是为了存空值
 Addr   string  `gorm:"column:y_addr;size:16"`
 Gender bool    `gorm:"default:true"`
}
type Student struct {
 Name string      `gorm:"type:varchar(12);not null;comment:用户名"`
 UUID string      `gorm:"primaryKey;unique;comment:主键"`
 Info StudentInfo `gorm:"embedded;embeddedPrefix:s_"`
}
相关文章
|
9天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
46 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
28天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
106 67
|
4天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
32 12
|
7天前
|
监控 算法 安全
解锁企业计算机监控的关键:基于 Go 语言的精准洞察算法
企业计算机监控在数字化浪潮下至关重要,旨在保障信息资产安全与高效运营。利用Go语言的并发编程和系统交互能力,通过进程监控、网络行为分析及应用程序使用记录等手段,实时掌握计算机运行状态。具体实现包括获取进程信息、解析网络数据包、记录应用使用时长等,确保企业信息安全合规,提升工作效率。本文转载自:[VIPShare](https://www.vipshare.com)。
19 0
|
21天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数
|
8月前
|
开发框架 安全 中间件
Go语言开发小技巧&易错点100例(十二)
Go语言开发小技巧&易错点100例(十二)
82 1
|
1月前
|
开发框架 Go 计算机视觉
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
|
2月前
|
Go 数据安全/隐私保护 开发者
Go语言开发
【10月更文挑战第26天】Go语言开发
43 3
|
2月前
|
Java 程序员 Go
Go语言的开发
【10月更文挑战第25天】Go语言的开发
39 3
|
5月前
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
177 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库