
Gorm 是 Go 语言的一个强大且易用的 ORM(对象关系映射)库,用于简化与关系型数据库的交互。支持主流数据库, 扩展性强,支持自定义钩子和插件。
Kitex 是一个高性能的 Go 语言 RPC 框架,由字节跳动开源,用于开发微服务架构中的 RPC 服务。支持 Thrift、Protobuf 等序列化协议。内置服务注册、负载均衡、熔断、限流和重试机制。
Hertz 是一个高性能、高扩展性的 HTTP 服务框架,同样由字节跳动开源,专注于构建高效的 HTTP 服务。
Gorm 文档:https://gorm.io/zh_CN/docs/index.html
Gorm 使用链式调用来设置条件等,因此条件的设置必须要在执行之前。Find、Update、Delete 等方法才是真正的执行函数。

DSN(Data Source Name)数据源名称
参数介绍:
[https://github.com/go-sql-driver/mysql#dsn-data-source-name](https://github.com/go-sql-driver/mysql#dsn-data-source-name)通用格式:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
Gorm 中的约定俗成:
gorm model名的蛇形复数形式作为表名,如: 结构体 ProductCategory 的默认表名是 product_categoriesCreatedAt、UpdatedAt字段作为创建时间和更新时间Gorm 支持的数据库: MySQL、PostgreSQL、SQLite 和SQL Server
通过驱动来连接数据库,要连接其他类型的数据库,则需要自行开发/复用开发驱动
以 sql server 数据库连接为例,


Gorm model使用 Gorm tag(反引号)来标记,设置字段名、主键、默认值等
upsert:表中存在指定值则更新,不存在则添加
可以使用clause.OnConflict来处理创建数据时的数据冲突

DoNothing表示不处理冲突
使用tag设置字段默认值:


注意事项:
First时,查询不到数据会返回ErrRecordNotFound,而使用Find查询不到,不会返回错误因此更多使用
Find
0、""、 false或其他零值,该字段不会被用于构建查询条件,使用 Map 来构建查询条件则会加上零值的字段
更新字段时,要使用 Model()来指定表名,特别是更新单个列时!当 updates中传递了表名,则不需要 Model了,但是最好都加上
同样的,使用 Struct 更新时,只会更新非零值,如果需要更新零值,可以使用 Map 更新或使用 Select 选择字段。

在表结构体中需要额外定义一个 gorm.DeletedAt字段,来表明软删除

定义了软删除字段后,调用 Delete时,并没有从磁盘中删除掉,只是在 deleted_at字段中设置删除时间,并且不能通过正常查询方法来查询到软删除的数据
查询软删除数据需要使用 Unscoped方法
Gorm 提供了 Begin、Commit、Rollback

注意:
Begin开启事务后,会返回当前数据库的固化链接(和 db 一样都是 db 对象),在事务中应该使用该返回值,而不是 db
更好的方式:
Gorm 中提供了Transaction方法用于自动提交事务,出错时回滚事务,避免了 commit 和 rollback 的漏写

Hook是在数据创建、查询、更新、删除等操作之前和之后_自动调用_的函数

在 Hook 操作中,会与中间的操作开启同一个默认事务,以保证数据的一致性。
若在 Hook 中或语句执行中返回错误,Gorm 会停止后续操作并进行事务回滚
在进行更新、创建、删除操作时,Gorm 会为该语句自动开启一个默认事务,这会降低性能
SkipDefaultTransaction来关闭默认事务PrepareStmt缓存预编译语句,可以提高后续调用速度,提升大约 35%的性能

乐观锁和悲观锁是两种在数据库中控制并发访问的方法,用于保证数据的一致性和正确性。它们的核心区别在于对资源冲突的处理策略:

官方文档:https://www.cloudwego.io/zh/docs/kitex/getting-started/
kitex 服务默认监听 8888 端口
IDL(Interface Definition Language):是一种用来定义服务接口及其数据结构的语言
主要作用:
如果我们要进行 RPC,就需要知道对方的接口是什么,需要传什么参数,同时也需要知道返回值是什么样的。这时候,就需要通过 IDL 来约定双方的协议,就像在写代码的时候需要调用某个函数,我们需要知道函数签名一样。
下面这个是 thrift 协议的 IDL,不同协议,IDL 规则不同

使用下面的命令通过 thrift 的 IDL 文件生成代码
kitex -module example -service example echo.thrift
生成文件如下:

build.sh:构建脚本,用于构建可执行文件
kitex_gen:IDL 内容相关的生成代码,主要是基础的服务器端和客户端代码
main.go:程序入口
handler.go:在该文件中实现 IDL server 定义的方法
handler.go中自动生成的内容

在其中编写代码逻辑就可以了
创建 RPC 的客户端,只要客户端和服务端所使用的协议一致就可以(thrift、gRPC)

WithHostPorts指定 ip 和端口,但是这样的话,服务发现就会失效
使用微服务时,更多的是使用服务发现与注册
发起 RPC 请求

在 req 中写入要处理的请求逻辑代码
其他代码 kitex 已经自动生成了,直接调用Echo就可以
Kitex 已经对接了主流的服务注册与发现中心,如:ETCD、Nacos 等
通过把server注册到服务注册中心,client到服务中心获取数据
服务端:

上述代码将 server 注册到 ETCD 服务中心,并 run 该服务:
在NewEtcdRegister使用 ETCD 扩展时,要指定 ETCD 集群的地址和端口
使用NewServer创建一个服务,然后Run,这样 server 就被注册到了 ETCD 中
客户端:
客户端发现服务的代码

NewEtcdResolver创建服务发现对象,参数传递 ETCD 集群的地址,此处的 err 必须要处理
MustNewClient或NewClient传入服务名来过滤集群中的服务,并传入服务发现对象
然后设置超时并发送请求

XDS:用于流量路由
Hertz 的基本使用

上面的代码,创建服务并监听 8080 端口并注册了一个 GET 方法的路由函数
server.Default或者server.New都可以创建一个 Hertz 对象
区别:Default默认继承recover中间件,New没有继承
GET注册 get 路由,其中有两个上下文,一个用于传递原信息,一个专注于请求的处理
Hertz 提供了标准的 http 方法的路由注册

Hertz 支持路由分组

支持参数路由和通配路由,路由优先级为:静态路由 > 命名路由 > 通配路由

Hertz 提供了Bind、Validate、BindAndValidate用于进行参数绑定和校验
参数绑定是用于从 HTTP 请求中提取参数并将其解析到结构体或变量的一种功能。

主要分为客户端中间件和服务端中间件
如下面这个简单的中间件代码

多个中间件使用洋葱模型调用,通过Next调用下一个
Use注册中间件
Hertz 也提供了客户端的功能,用户帮助用户发送请求

Hertz 提供了代码生成工具 Hz,通过定义 IDL(interface description language)文件即可生成对应的基础服务代码,包括服务端代码和客户端代码
如以下 IDL 文件

生成文件目录结构

main.go启动文件
router.go、router_gen.go是注册路由
下面是生成的 hello_service.go文件

