go框架三件套(web/rpc/orm)|青训营笔记

185 阅读5分钟

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

go框架三件套(web/rpc/orm)

三件套的介绍

Hertz

http框架

Kitex

是字节内部的go的rpc框架,具有高性能、强可扩展的主要特点,支持多协议并且拥有丰富的开源扩展

Gorm

orm框架,和Java中的MyBatis作用相当

Gorm的使用

gorm的基本使用

首先是连接数据库,连接方式是使用数据库的驱动
首先根据数据库表的结构使用结构体定义gorm model,使用函数为model定义表名。 在主函数中gorm.Open(mysql.Open(...),&gorm.COnfig{})连接数据库,然后就可以使用函数进行增删改查。
gorm中的约定如下

  1. gorm使用名为ID的字段作为主键
  2. 使用结构体的蛇形负数作为表名
  3. 字段名的蛇形作为列表
  4. 使用CreatedAt、UpdatedAt字段作为创建、更新时间 gorm目前支持的数据库MySQL,SQLServer,PostgreSQL,SQLite,gorm使用驱动来连接数据库,如果需要连接其他类型的数据库,可以复用/自行开发驱动

gorm查询数据库

查询一条数据使用First(&保存的变量),使用First时,需要注意查询不到数据会返回ErrRecordNotFound。

db, err := gorm.Open(mysql.Open(dsn, &gorm.Config{}))
if err != nil {
    panic("failed to connect database")
}
u := &User{}
// 获取第一条记录(主键升序),查询不到数据则返回 ErrRecordNotFound
db First(u)

使用Find查询多条数据,查询不到数据不会返回错误

users := make([]*User, 0)
result := db.Where("age > 10").Find(&users) // SELECT * FROM users where age > 10

当使用结构体作为条件时,gorm只会查询非零字段。这意味着如果您的字段值为0,false或者其他零值,该字段不会被用于构建查询条件,使用Map来构建查询条件。

// SELECT * FROM users WHERE name = "jinzhu";
db.Where(&User{Name:"jinzhu", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
db.Where(map[string]interface{}{"Name}: "jinzhu", "Age": 0).Find(&users)

gorm 更新数据

调用链从前至后,分别为Model(),Where(),Update(),更新的时候会自动更新表中updateed_at字段

// 条件更新单个列
db.Model(&User{ID: 111}).Where("age > ?", 10).Update("name", "hello")
// 条件更新多个列
db.Model(&User{ID: 111}).Updates(User{Name: "hello", Age: 18})

使用结构体更新时,只会更新非零值,如果需要更新零值可以使用Map或使用Select选择字段

gorm 删除数据

分为物理删除和逻辑删除

  1. 物理删除:db.Delete(&User{}, 10)
  2. 软删除:如果在对象的结构体中设置Deleted属性,属性的类型为gorm.DeletedAt类型,那么调用db.Delete()函数的时候就会进行软删除
    拥有软删除能力的Model调用Delete时,记录不会被从数据库真正删除。但GORM会将DeletedAt置为当前时间,并且你不会再通过正常的查询方法找到该记录。
    使用unsoped可以查询到被软删的数据

gorm事务

gorm提供了Begin、Commit、Rollback方法用于使用事务

db, err := gorm.Open(dsn, &gorm.Config{})
tx := db.Begin()  // 开始事务
// 在事务中执行一些db操作(从这里开始,您应该使用‘tx’,而不是‘db’)
if err = tx.Create(&User{Name: "name"}).Error; err != nil {
    tx.Rollback()
    // 需要错误时回滚事务
    return
}
if err = tx.Create(&User{Name: "name1"}).Error; err != nil {
    tx.Rollback()
    return
}
// 提交事务
tx.Commit()

gorm提供了Tansaction方法用于自动提交事务,避免用户漏写Commit,Rollback

db, err := gorm.Open(dsn, &gorm.Config{})
if err = db.Transaction(func(tx *gorm.DB) error {
    if err = tx.Create(&User{Name: "name"}).Error; err != nil {

        return
    }
    if err = tx.Create(&User{Name: "name1"}).Error; err != nil {
        tx.Rollback()
        return
    }
    return nil
}); err != nil {
    return
}

// 提交事务
tx.Commit()

gorm hook

gorm提供了curd的hook能力。hook是在创建、查询、更新、删除等操作之前、之后自动调用的函数。如果任何hook返回错误,gorm将停止后续的操作并回滚事务。
这个功能和Java的spring中也很常见

kitex

代码生成工具

目前代码生成工具对windows的支持不完善,建议使用虚拟机或者wsl2

定义IDL

安装好代码生成工具后需要使用IDL定义服务与接口
如果我们要进行RPC,就需要知道对方的接口是什么,需要传什么参数,同时也需要知道返回值是什么样的。这时候,就需要通过IDL来约定双方的协议,就像在写代码的时候需要调用某个函数,我们需要知道函数签名一样。

namespace go api
struct Request{
    1:string message
}
struct Response{
    1: string message
}
service Echo {
    Response echo (1: Request req)
}

Kitex 生成代码

使用ketex -module example -service example echo.thrift命令生成代码
build.sh : 构建脚本 ketex_gen : IDL内容相关的生成代码,主要是基础的Server/Client代码 main.go : 程序入口 handler.go : 用户在该文件里实现IDL service定义的方法

kitex生成代码.png

kitex 基本使用

Kitex Client 发起请求

在go服务中,即有server也有client,client用于向其他服务发起请求

kitex发起请求.png

kitex 服务注册与发现

目前kitex的服务注册与发现已经对接了主流的服务注册与发现中心,如Nacos,ETCD等

Hertz

Hertz基本使用

服务监听8080端口,并注册了一个GET方法的路由函数

Hertz基本使用.png 提供了路由组,用于支持路由分组的功能

Hertz的路由.png

提供了参数路由和通配路由,路由的优先级:静态路由>命名路由>通配路由

Hertz的路由1.png

Hertz参数绑定

提供了Bind,Validate,BindAndValidate函数用于进行参数绑定和校验

Hertz参数绑定.png

Hertz 代码生成工具

Hertz提供了代码生成工具Hz,通过定义IDL(inteface description language)文件即可生成对应的基础服务代码

Hertz 代码生成工具.png