Go 框架三件套详解(Web/RPC/ORM) | 青训营笔记

72 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

主要记录课程的重点和课上所讲项目的每一步以及我的思考

今天的课程主要讲解了GORM,Kitex,Hertz 的基本使用方法。因为时间和学习进度问题,本次笔记将主要讲解GORM的内容。

Gorm

概念

首先我们要了解ORM的概念,ORM(Object Relational Mapping),意思是对象关系映射。 数据库会提供官方客户端驱动,但是需要自己处理 SQL 和结构体的转换。 使用 ORM 框架让我们避免转换,写出一些无聊的冗余代码。理论上 ORM 框架可以让我们脱离 SQL,但实际上还是需要懂 SQL 才可以使用 ORM。Gorm 是 Golang 的一个ORM框架。Gorm官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server

Gorm的基本使用

连接数据库

首先要导入Gorm和MySQL驱动

import ( "gorm.io/driver/mysql" // gorm mysql 驱动包 
"gorm.io/gorm"// gorm 
)

连接

dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, DBname, timeout) // Open 连接 
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) 
if err != nil {
panic("failed to connect mysql.") 
}

创建数据

使用 db.Create  方法,传入结构体的指针创建

user := User{UserName: "l", Password: "ddd"}
result := db.Create(&user)

常用的插入数据

fmt.Println("ID:", user.ID)                       // 插入的主键
fmt.Println("error:", result.Error)               // 返回的 error
fmt.Println("rowsAffected:", result.RowsAffected) // 插入的条数

通过select选择指定字段

user := User{UserName: "lzq", Password: "ccc"}
result := db.Select("UserName").Create(&user)

当需要批量插入时,传入一个切片即可

users := []User{
    {UserName: "lzq", Password: "aaa"},
    {UserName: "qqq", Password: "bbb"},
    {UserName: "gry", Password: "ccc"},
}
db.Create(&users)

查询数据

查询单个对象

gorm 提供了 First、Take、Last 方法。它们都是通过 LIMIT 1  来实现的,分别是主键升序、不排序和主键降序

user := User{}

// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

根据主键查询

在 First/Take/Last 等函数中设置第二个参数,该参数被认作是 ID。可以选择 int 或 string 类型

db.First(&user, 10)

db.First(&user, "10")

查询多个对象

使用 Find 方法查询多个对象

users := []User{}
result := db.Find(&users)

更新数据

更新所有字段

使用 Save 方法更新所有字段,即使是零值也会更新

db.First(&user)
user.UserName = ""
db.Save(&user)

更新单列

使用 Model 和 Update 方法更新单列。

可以使用结构体作为选取条件,仅选择 ID

user.ID = 12
db.Model(&user).Update("user_name", "lzq")

也可以在 Model 中设置空结构体,使用 Where 方法自己选取条件

db.Model(&User{}).Where("user_name", "gry").Update("user_name", "gry2")

更新多列

使用 Updates 方法进行更新多列。支持 struct 和 map 更新。当更新条件是 struct 时,零值不会更新,如果确保某列必定更新,使用 Select 选择该列

删除数据

物理删除

db.Unscoped().Delete(&order) // DELETE FROM orders WHERE id=10;

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力。拥有软删除能力的模型调用 Delete 时,记录不会被从数据库中真正删除。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过正常的查询方法找到该记录。

// user 的 ID 是 `111` 
db.Delete(&user) 
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;  
// 批量删除 
db.Where("age = ?", 20).Delete(&User{}) 
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;  
// 在查询时会忽略被软删除的记录 
db.Where("age = 20").Find(&user) 
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

可以使用 Unscoped 找到被软删除的记录

db.Unscoped().Where("age = 20").Find(&users) 
// SELECT * FROM users WHERE age = 20;

事物

要在事务中执行一系列操作,一般流程如下:

db.Transaction(func(tx *gorm.DB) error {
  // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
  if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
    // 返回任何错误都会回滚事务
    return err
  }

  if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
    return err
  }

  // 返回 nil 提交事务
  return nil
})

Hook

Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。

如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。

总结

本次课程讲解了三个主流框架,并有实战演示。因为精力问题,这次学习并不太好,也没用预先安装好相应的程序,没有办法跟着一块做。在明后天会再次补上。

引用

该文章部分内容来自于以下课程或网页: