gin框架学习-Gorm入门指南

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Snake Case命名风格,就是各个单词之间用下划线(_)分隔,首字母大写区分一个单词,例如: CreateTime的Snake Case风格命名为create_time

前言


感谢开源项目gin-vue-admin,以及1010工作室的视频教程

本人学识尚浅,如有错误,请评论指出,谢谢!

详细可见个人博客:https://linzyblog.netlify.app/

一、GORM介绍


1、GORM概述


GORM一个目前比较热门的,使用简单,对开发人员友好的 Golang ORM 库。


GORM框架是go的一个数据库连接及交互框架,主要是把struct类型和数据库记录进行映射,数据库语句复杂的情况下可以直接手写语句,一般用于连接关系型数据库,这里我主要使用MySQL数据库。


对象关系映射(英语:Object Relational Mapping,简称ORM): 通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射,可以使用面向对象的范例从数据库中查询和操作数据。


简而言之:代码结构即是数据库结构,代码行为就是数据库行为。


2、为什么选择GORM?


特性:


  • 数据库连接(以MySQL为例)和自动建表方便。
  • 文档内容详细全面,适合快速入门上手。
  • 支持关联 (一对一,一对多,多对多的关系)。
  • 带有Create,Save,Update,Delete,Find 中钩子方法。
  • 支持 Preload、Joins 的预加载,对于关联查询很重要,主要用于显示关联子结构的内容。
  • 支持事务,嵌套事务。
  • 可以使用Context、预编译模式、DryRun 模式。
  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD。
  • SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询。
  • 复合主键,索引,约束。
  • 自定义 Logger。
  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
  • 开发者友好。


二、安装


GORM库github地址: https://github.com/go-gorm/gorm

GORM库文档地址:https://gorm.io/zh_CN/docs/


第一步:

很重要,go mod 包管理工具项目的开始都需要先做这一步


go mod init name


第二步:


操作MySQL数据库需要两个包


  • GORM包
  • MySQL驱动包


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


或者:


你可以直接在文件里面直接导入这两个库的引用


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


再用 go mod tidy的方法自动导入库。


三、快速入门


package main
import (
  "fmt"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
type User struct {
  gorm.Model
  Name string
  Age  uint
}
func main() {
  //我这里用到数据库是mysql,需要配置DSN属性[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
  dsn := "root:123456@tcp(127.0.0.1:3306)/go_test?charset=utf8&parseTime=True"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }
  // 迁移 schema
  db.AutoMigrate(&User{})
  // Insert 插入语句
  db.Create(&User{Name: "linzy", Age: 23})
  // Select 查询语句
  var user User
  db.First(&user, 1) // 根据整形主键查找
  fmt.Println(user)
  db.First(&user, "name = ?", "linzy") // 查找 name 字段值为 linzy 的记录
  fmt.Println(user)
  // Update 更新语句 - 将 User 的 age 更新为 18
  db.Model(&user).Update("Age", 18)
  // Update - 更新多个字段
  db.Model(&user).Updates(User{Name: "linzy", Age: 88}) // 仅更新非零值字段
  db.Model(&user).Updates(map[string]interface{}{"Name": "linzy", "Age": 23})
  // Delete 删除语句 - 删除 ID为1
  db.Delete(&user, 1)
}

cb8fe016924c4802aea2da517b6f9265.png


四、模型定义


GORM负责将对模型的读写操作翻译成sql语句,然后GORM再把数据库执行的sql语句后返回的结果转化为我们定义的模型对象。


1、模型定义介绍


模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成。


例如:


type User struct {
  ID           uint
  Name         string
  Email        *string
  Age          uint8
  Birthday     *time.Time
  MemberNumber sql.NullString
  ActivedAt    sql.NullTime
  CreatedAt    time.Time
  UpdatedAt    time.Time
}


默认gorm对struct字段名使用Snake Case命名风格转换成mysql表字段名(需要转换成小写字母)。


Snake Case命名风格,就是各个单词之间用下划线(_)分隔,首字母大写区分一个单词,例如: CreateTime的Snake Case风格命名为create_time


2、约定


GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间


遵循 GORM 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们


3、gorm.Model


GORM 定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt


// gorm.Model 的定义
type Model struct {
  ID        uint `gorm:"primaryKey"` //设置主键
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}


可以将它嵌入到你的结构体中,以包含这几个字段


4、高级选项


1)字段级权限控制


可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许您用标签控制字段级别的权限。这样您就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略


注意: 使用 GORM Migrator 创建表时,不会创建被忽略的字段


type User struct {
  Name string `gorm:"<-:create"`          // 允许读和创建
  Name string `gorm:"<-:update"`          // 允许读和更新
  Name string `gorm:"<-"`                 // 允许读和写(创建和更新)
  Name string `gorm:"<-:false"`           // 允许读,禁止写
  Name string `gorm:"->"`                 // 只读(除非有自定义配置,否则禁止写)
  Name string `gorm:"->;<-:create"`       // 允许读和写
  Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
  Name string `gorm:"-"`                  // 读写操作均会忽略该字段
}


2)创建 / 更新时间追踪(纳秒、毫秒、秒、Time)


GORM 约定使用 CreatedAt、UpdatedAt 追踪创建 / 更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间


要使用不同名称的字段,您可以配置 autoCreateTim、autoUpdateTim 标签


如果您想要保存 UNIX(毫 / 纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可


type User struct {
  CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
  UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
  Updated   int64     `gorm:"autoUpdateTime:nano"`  // 使用时间戳填纳秒数充更新时间
  Updated   int64     `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
  Created   int64     `gorm:"autoCreateTime"`       // 使用时间戳秒数填充创建时间
}


3)嵌入结构体


对于匿名字段,GORM 会将其字段包含在父结构体中,例如:


type User struct {
  gorm.Model
  Name string
}
// 等效于
type User struct {
  ID        uint `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
  Name      string
}


对于正常的结构体字段,你也可以通过标签 embedded 将其嵌入,例如:


type Author struct {
  Name  string
  Email string
}
type Blog struct {
  ID      int
  Author  Author `gorm:"embedded"`
  Upvotes int32
}
// 等效于
type Blog struct {
  ID      int64
  Name    string
  Email   string
  Upvotes int32
}


并且,您可以使用标签 embeddedPrefix 来为 db 中的字段名添加前缀,例如:


type Blog struct {
  ID      int
  Author  Author `gorm:"embedded;embeddedPrefix:author_"`
  Upvotes int32
}
// 等效于
type Blog struct {
  ID          int64
  AuthorName  string
  AuthorEmail string
  Upvotes     int32
}


4)字段标签


声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格


标签名 说明
column 指定 db 列名

type

列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null、size, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INSTREMENT

size 指定列大小,例如:size:256
primaryKey 指定列为主键
unique 指定列为唯一
default 指定列的默认值
precision 指定列的精度
scale 指定列大小
not null 指定列为 NOT NULL
autoIncrement 指定列为自动增长
embedded 嵌套字段
embeddedPrefix 嵌入字段的列名前缀
autoCreateTime 创建时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano
autoUpdateTime 创建 / 更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
index 根据参数创建索引,多个字段使用相同的名称则创建复合索引
uniqueIndex index 相同,但创建的是唯一索引
check 创建检查约束,例如 check:age > 13


5)关联标签


GORM 允许通过标签为关联配置外键、约束、many2many 表


五、连接数据库


GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server


1、MySQL


连接MySQL主要有两个步骤:


1)配置DSN (Data Source Name)


  • DSN介绍:gorm库使用dsn作为连接数据库的参数,dsn翻译过来就叫数据源名称,用来描述数据库连接信息。一般都包含数据库连接地址,账号,密码之类的信息。


  • DSN字段格式:


[username[:password]@][protocol[(address)]]/dbname[?param1=value1&…¶mN=valueN]


//mysql dsn格式
//涉及参数:
//username   数据库账号
//password   数据库密码
//host       数据库连接地址,可以是Ip或者域名
//port       数据库端口
//Dbname     数据库名
username:password@tcp(host:port)/Dbname?charset=utf8&parseTime=True&loc=Local


2)使用gorm.Open连接数据库


import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}


注意:想要正确的处理 time.Time ,您需要带上 parseTime 参数,要支持完整的 UTF-8 编码,您需要将 charset=utf8 更改为 charset=utf8mb4


MySQl 驱动程序提供了 一些高级配置 可以在初始化过程中使用,例如:


db, err := gorm.Open(mysql.New(mysql.Config{
  // DSN data source name
  DSN:                       "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", 
  // string 类型字段的默认长度
  DefaultStringSize:         256,
  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持                                                                        
  DisableDatetimePrecision:  true,
  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引                                                                       
  DontSupportRenameIndex:    true,
  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列                                                                       
  DontSupportRenameColumn:   true,
  // 根据当前 MySQL 版本自动配置                                                                       
  SkipInitializeWithVersion: false,                                                                      
}), &gorm.Config{})


1)自定义驱动


GORM 允许通过 DriverName 选项自定义 MySQL 驱动,例如:


import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
func main() {
  db, err := gorm.Open(mysql.New(mysql.Config{
    DriverName: "my_mysql_driver",
    DSN:        "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local", 
    // Data Source Name,参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name
  }), &gorm.Config{})
}


2)现有的数据库连接


GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB


import (
  "database/sql"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
func main() {
  sqlDB, err := sql.Open("mysql", "mydb_dsn")
  gormDB, err := gorm.Open(mysql.New(mysql.Config{
    Conn: sqlDB,
  }), &gorm.Config{})
}


3)GORM配置


gorm.Config{}: GORM 提供可以在初始化时使用的配置。


type Config struct {
  //跳过默认事务:为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。
  SkipDefaultTransaction   bool
  //命名策略:用户通过覆盖默认的NamingStrategy来更改命名约定
  NamingStrategy           schema.Namer
  //Logger:通过覆盖此选项更改 GORM 的默认 logger
  Logger                   logger.Interface
  //NowFunc:更改创建时间使用的函数
  NowFunc                  func() time.Time
  //DryRun:生成 SQL 但不执行,可以用于准备或测试生成的 SQL
  DryRun                   bool
  //PrepareStmt:PreparedStmt 在执行任何 SQL 时都会创建一个 prepared statement 并将其缓存,以提高后续的效率
  PrepareStmt              bool
  //禁用嵌套事务
  DisableNestedTransaction bool
  //AllowGlobalUpdate:启用全局 update/delete
  AllowGlobalUpdate        bool
  //DisableAutomaticPing:在完成初始化后,GORM 会自动 ping 数据库以检查数据库的可用性
  DisableAutomaticPing     bool
  //DisableForeignKeyConstraintWhenMigrating:在 AutoMigrate 或 CreateTable 时,GORM 会自动创建外键约束
  DisableForeignKeyConstraintWhenMigrating bool
}


GORM配置详细内容直接看文档,我后续会再写一篇:点击跳转


2、连接池


在高并发实践中,为了提高数据库连接的使用率,避免重复建立数据库连接带来的性能消耗,会经常使用数据库连接池技术来维护数据库连接。


GORM 使用 database/sql 维护连接池


sqlDB, err := db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)


参考GORM中文文档:https://learnku.com/docs/gorm/v2/connecting_to_the_database/9731#64cea3

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
Go API 网络架构
Gin框架快速入门1
Gin框架快速入门1
128 0
|
7月前
|
JSON 关系型数据库 Go
gorm 教程三 gen代码生成框架
gorm 教程三 gen代码生成框架
264 0
|
6月前
|
JSON 中间件 API
Gin框架笔记(一) Gin框架的安装与Hello World
Gin框架笔记(一) Gin框架的安装与Hello World
229 0
|
6月前
|
JSON 前端开发 Java
|
6月前
|
前端开发 中间件 关系型数据库
|
SQL 关系型数据库 Go
Golang微服框架Kratos与它的小伙伴系列 - ORM框架 - GORM
[GORM](https://gorm.io/index.html) 是基于Go语言实现的ORM库,它是Golang目前比较热门的数据库ORM操作库,对开发者也比较友好,使用非常方便简单。
157 0
|
Go API
gin框架学习-快速安装gin
Gin 是一个用 Go (Golang) 编写的 Web 框架,由于 httprouter,它具有 martini 的 API,性能提高了 40 倍。具有高性能的优点。
165 0
gin框架学习-快速安装gin
|
Go PHP
Gin从入门到精通—如何理解安装Gin并在本地运行
Gin从入门到精通—如何理解安装Gin并在本地运行
518 0
Gin从入门到精通—如何理解安装Gin并在本地运行
|
安全 中间件
Gin框架学习(七)
来这里学Gin框架,目标明确不迷茫。
120 0
Gin框架学习(七)
Gin框架学习(九)
来这里学习gin框架,目标明确不迷茫。
157 0
Gin框架学习(九)