这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
一、本堂课重点内容
- 三件套(GORM、Kitex、Hertz)介绍
- 三件套的使用
- 实战案例介绍
二、详细知识点介绍
三件套介绍
GORM
GORM是一个已经迭代了10年+的功能强大的ORM框架,在字节内部被广泛使用并且拥有非常丰富的开源扩展。
Kitex
Kitex是字节内部的Golang微服务RPC框架,具有高性能、强可扩展的主要特点,支持多协议并且拥有丰富的开源扩展。
Hertz
Hertz是字节内部的HTTP框架,参考了其他开源框架的优势,结合字节跳动内部的需求,具有高易用性、高性能、高扩展性特点。
三件套的使用
GORM
GORM 基础使用
其中
Product为定义的 gorm model,TableName()为实现的方法,从而定义表名,在结构体中,常添加 gorm.Model来实现一些基本的字段(如ID、CreatedAt等),在 main函数中使用 gorm.Open()来开启一个数据库连接,第一个参数配置各种数据库的驱动,此处使用的是mysql,第二个参数用于设置连接的配置。
之后便可以进行CRUD操作。
GORM 支持的数据库
目前GORM支持的数据库包括MySQL、SQL Server、PostgreSQL、SQLite,配置方法如上述基础使用中 gorm.Open()描述的第一个参数所示。
除此之外,若需要连接其他类型的数据库,可以复用或自行开发驱动。
GORM 相关的CRUD操作
具体可以参考GORM文档
GORM 事务
GORM提供了 Begin、Commit、Rollback方法用于事务。
除此之外,还提供了 Transaction方法用于自动提交事务,避免漏写 Commit和 Rollback。
GORM Hook
GORM还提供了CRUD的Hook能力,其为创建、查询、更新、删除等操作之前、之后自动调用的函数。
如果任何Hook返回了错误,GORM将停止后续操作并回滚。
使用方法还请参考GORM Hook。
GORM 性能提高
对于创建、更新、删除,为了确保数据的完整性,GORM会将它们封装在事务内运行。但是会降低一定的性能,可以使用SkipDefaultTransaction关闭默认事务(加在之前 gorm.Open()的第二个参数里)。
使用PrepareStmt可以缓存预编译语句来提高后续调用的速度,同样加在 gorm.Open()的第二个参数里。
GORM 生态
常用扩展
| 扩展名 | 地址 |
|---|---|
| GORM 代码生成工具 | github.com/go-gorm/gen |
| GORM 分片库方案 | github.com/go-gorm/sha… |
| GORM 手动索引 | github.com/go-gorm/hin… |
| GORM 乐观锁 | github.com/go-gorm/opt… |
| GORM 读写分离 | github.com/go-gorm/dbr… |
| GORM OpenTelemetry扩展 | github.com/go-gorm/ope… |
更多请参考GORM文档
GORM 使用注意事项
- 字段默认值使用go tag来定义,
`gorm:"default:xxx"` - 使用
First查询时,若查不到数据会返回ErrRecordNotFound。 - 使用
Find查询时,查询不到不会返回错误。 - 当使用结构体作为查询条件(Where)时,GORM只会查询非零值字段(防止未赋值),因此,字段为零值的(0、""、false等)将不会用于构建查询条件,要将其用于构建查询条件时,需要使用Map来构建查询条件。
- Update语句中使用结构体时,只会更新非零值,如果需要更新零值可以使用Map更新或使用Select选择字段。
- GORM提供了
gorm.DeletedAt来帮用户实现软删。拥有软删的Model调用Delete时,记录不会真正从数据库中删除,但是会将其DeletedAt设置为当前时间,并且无法通过正常查询找到该记录。要查询该软删记录,可以使用Unscoped。
Kitex
Kitex目前对Windows支持尚不完善,代码生成工具只能在Linux下运行。
定义IDL
如果需要进行RPC,就需要知道对方的接口是什么,需要传递什么参数,同时也要知道返回值是什么。此时就需要使用IDL来约定双方的协议,就像写代码时调用函数,需要知道函数签名一样。
namespace go api
struct Request {
1: string message
}
struct Response {
1: string message
}
service Echo {
Response echo(1: Request req)
}
Kitex 生成代码
使用 kitex -module example -service example echo.thrift来生成代码。
得到与上图类似的目录结构。
build.sh是用于构建项目的脚本kitex_gen是IDL内容相关的生成代码,主要是基础的Server/Client代码main.go是程序的入口handler.go是用户要实现的service方法(IDL中定义的)
Kitex 使用方法
参考Kitex 文档
Kitex 生态
常用扩展
| 扩展名 | 地址 |
|---|---|
| XDS 扩展 | github.com/kitex-contr… |
| opentelemetry 扩展 | github.com/kitex-contr… |
| ETCD 服务注册与发现扩展 | github.com/kitex-contr… |
| Nacos 服务注册与发现扩展 | github.com/kitex-contr… |
| Zookeeper 服务注册与发现扩展 | github.com/kitex-contr… |
| polaris 扩展 | github.com/kitex-contr… |
| 丰富的示例代码与业务Demo | github.com/cloudwego/k… |
Hertz
Hertz 基础使用
上述为Hertz实现的,该服务监听8080端口并注册了一个GET方法的路由函数。
Hertz 路由
Hertz提供了GET、POST、PUT、DELETE、ANY等方法用于注册路由,如下图所示。
此外,Hertz还提供了路由组(Group)的能力,用于支持路由分组的功能
此外,还提供了参数路由和通配路由,路由的优先级从大到小依次为:
- 静态路由
- 命名路由
- 通配路由
Hertz 参数绑定
Hertz提供了Bind、Validate、BindAndValidate函数用于进行参数绑定和校验。
Hertz 中间件
Hertz 的中间件主要分为客户端中间件和服务端中间件,比如:
Hertz 代码生成工具
Hertz 提供了代码生成工具hz,通过IDL文件就可以生成对应的基础服务代码。
Hertz 更多内容
参考Hertz 文档
三、实践练习例子
项目介绍
在这次课程中介绍了一个Easy Note的实践项目。
其为使用Hertz、Kitex、GORM搭建,具有一定的业务逻辑的后端API项目。
下面的是服务使用到的相关技术:
| 服务名称 | 服务介绍 | 传输协议 | 主要技术栈 |
|---|---|---|---|
| demoapi | API服务 | HTTP | Kitex/Hertz |
| demouser | 用户数据管理 | Thrift | GORM/Kitex |
| demonote | 笔记数据管理 | Thrift | GORM/Kitex |
调用关系
更多内容
- 原项目地址:Easy Note
- 我的实践项目地址:my-easy-note(包含详细构建过程及注意事项)
四、课后个人总结
此次课程讲解了Golang中三个框架的使用以及注意事项,并给出了一个实践项目来巩固所学知识,所给出的实践项目有一些小问题,不过在查询资料之后都能够解决。
总的来说,这次课程的收获很大,对框架的理解也是更进一步了。