这是我参与「第五届青训营 」伴学笔记创作活动的第 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中的约定如下
- gorm使用名为ID的字段作为主键
- 使用结构体的蛇形负数作为表名
- 字段名的蛇形作为列表
- 使用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 删除数据
分为物理删除和逻辑删除
- 物理删除:
db.Delete(&User{}, 10) - 软删除:如果在对象的结构体中设置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 基本使用
Kitex Client 发起请求
在go服务中,即有server也有client,client用于向其他服务发起请求
kitex 服务注册与发现
目前kitex的服务注册与发现已经对接了主流的服务注册与发现中心,如Nacos,ETCD等
Hertz
Hertz基本使用
服务监听8080端口,并注册了一个GET方法的路由函数
提供了路由组,用于支持路由分组的功能
提供了参数路由和通配路由,路由的优先级:静态路由>命名路由>通配路由
Hertz参数绑定
提供了Bind,Validate,BindAndValidate函数用于进行参数绑定和校验
Hertz 代码生成工具
Hertz提供了代码生成工具Hz,通过定义IDL(inteface description language)文件即可生成对应的基础服务代码