这是我参与「第五届青训营」伴学笔记创作活动的第2天
本节课的重点内容如下:
- GORM框架的基本CRUD、事务、钩子函数等
- Kitex框架的基本使用、IDL语言、其代码生成等
- Hertz框架的基本使用
- 学习实战案例——笔记项目的写法
go框架三件套(Web/RPC/ORM)
GORM(ORM框架)
GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间
例子:
type User struct {
ID uint // 主键id
Name string // name
Email *string // email
Age uint8 // age
Birthday *time.Time // birthday
MemberNumber sql.NullString // member_number
ActivedAt sql.NullTime // actived_at
CreatedAt time.Time // created_at
UpdatedAt time.Time // updated_at
}
1、基本的CRUD
1)获取db连接
db, err := gorm.Open(mysql.Open(DSN),&gorm.Config())
其中DSN,指的是Data Source Name,需要填入指定格式的参数
格式: [username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
例子: user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local
2)查询
将结构体与表名相绑定
// 这个结构体用于映射表属性
type Student struct {
Id int64 // id 默认为主键
Name string // name
Tutor int64 // tutor
}
// 这个方法就用于绑定表名
func (student Student) TableName() string {
return "student"
}
简单查询语句
db.First(&student) 默认按照主键升序排序,取出第一条记录
相当于 select * from student order by student.Id limit 1
例子:
var student Student
db.First(&student) // select * from student order by student.Id limit 1
fmt.Println(student)
student = Student{}
db.First(&student, 4) // select * from student where id = 4 order by ...
fmt.Println(student)
student = Student{}
db.First(&student, "id = ?", 3) // select * from student where id = 3 order by
fmt.Println(student)
db.Take(&student) 获取一条记录,没有指定排序字段 相当于 SELECT * FROM student LIMIT 1;
db.Last(&student) 获取最后一条记录,按照主键降序排序 相当于SELECT * FROM student ORDER BY student.id DESC LIMIT 1;
复杂查询
GORM采用的是一种链式调用的方式,所以可以很方便的去拼接查询条件,但在Find()之后拼接的条件不会再生效
students := make([]*Student, 0)
db.Where("name = ?", "王五").Find(&students)
for _, std := range students {
fmt.Println(*std)
}
// {3 王五 3}
fmt.Println()
db.Where("id > ? and tutor <= ?", 3, 5).Find(&students)
for _, std := range students {
fmt.Println(*std)
}
// {4 赵六 4}
// {5 田七 5}
3)增加
db.Create(&nStudent) 向数据库中添加指定的数据
nStudent := Student{Id: 666, Name: "niubi", Tutor: 777}
result := db.Create(&nStudent)
fmt.Println(result.Error)
fmt.Println(result.RowsAffected)
4)更新
db.Model(&User{ID: 111}).Where("age > ?", 6666).Update("name", "hello")
// update user set name = "hello" where age > 6666 and id = 111
其中Model主要是用来通过结构体来传入表名,同时还可以将其属性作为兜底的where条件(会作为where条件来使用),一般的用法 Model(&结构体对象的引用{})
为什么要使用Model(&User{})?
我个人的想法是,更新语句是通过Update(column, value),来执行实际的 set column = value,也就是说Update中不带有任何可以判定目标表名的条件,所以就需要Model来作为一个补充,帮助传入表名
5)删除
2、事务
3、钩子函数Hook
Kitex(RPC框架)
1、IDL(接口定义语言,用来定义接口参数、返回值等)
struct Request 和 struct Response 结构体就相当于该RPC接口的请求与响应结构
service Echo:指明该服务的名称为Echo,其中有一个接口叫echo,能够接收Request类型的参数,响应值为Response类型
2、Kitex生成的代码结构
Kitex自带代码生成工具,在编写好服务对应的IDL文件(可以是thrift类型,也可以是proto类型)之后,就可以通过相应的指令来自动生成代码
kitex -module example -service example echo.thrift
上述命令中,-module 表示生成的该项目的 go module 名,-service 表明我们要生成一个服务端项目,后面紧跟的 example 为该服务的名字。最后一个参数则为该服务的 IDL 文件。
3、对接服务注册中心,获取服务对象
普通的传入服务地址
hello.NewClient("hello", client.WithHostPorts("0.0.0.0:8888")) 传入服务实例地址
对接服务注册中心
hello.NewClient("hello", client.WithResolver(r)) 传入注册中心,通过注册中心来获取服务实例
Hertz(Web框架)
Hertz是一个 Golang 微服务 HTTP 框架,在设计之初参考了其他开源框架 fasthttp、gin、echo 的优势, 并结合字节跳动内部的需求,使其具有高易用性、高性能、高扩展性等特点
1、路由操作(与gin类似)
注册路由
参数路由和通配路由
参数路由如果请求没有提供参数,就无法匹配,无法无视参数
通配路由如果请求没有提供参数,可以匹配,相当于忽视了参数段 —— 所以应该更加常用?
例子(可以看出与Gin的使用及其相似)
// 使用gin
r := gin.Default()
// 配置路由
r.GET("/page/get/:id", func(c *gin.Context) {
topicId := c.Param("id")
data := controller.QueryPageInfo(topicId)
c.JSON(200, data)
})
err = r.Run() // 启动服务
if err != nil {
return
}
// 使用Hertz
h := server.Default() // 启动服务
// 配置路由
h.GET("/page/get/:id", func(c context.Context, ctx *app.RequestContext) {
topicId := ctx.Param("id")
data := controller.QueryPageInfo(topicId)
ctx.JSON(200, data)
})
h.Spin() // 启动服务
2、参数绑定(自动填充参数,不用自己取)
这里定义了一个Args结构体,其中结构体的每个属性都与一个参数相对应
当调用 c.BindAndValidate(&args)时,herz框架会自动将请求中的对应属性填充进args中
3、中间件(不知道这里的中间件是什么概念)
实战案例
项目功能介绍
没写了,记录一下笔记项目的地址,自己留着看代码