课程例子讲解——查询
Post和Topic结构体
-
post
- id (
int64) - title (
string) - content (
string) - create_time (
int64)
- id (
-
post
- id (
int64) - parent_id (
int64) - content (
string) - create_time (
int64)
- id (
本地文件索引的初始化
根据map来初始化两个文件的索引
一个是话题topic (map[int64]),一个是回帖的list数组(map[int64][])
主要代码思路为
- 通过
os.Open打开对应文件,如果打开文件过程中出现错误,就会返回错误。 - 创建一个
Scanner对象,用于逐行读取打开的文件内容。 - 创建一个临时的
map索引,用于暂时存储从文件中读取的话题数据。 - 通过
for scanner.Scan(){...}这样子的循环,每次读取文件的一行内容,并将其解析为对应的结构体,将解析得到的结构体对象添加到刚刚创建的临时map中。 - 文件读取完毕后,将临时存储的
map索引,赋予给全局的map,完成索引的初始化
Router
- URL:/community/page/get/
- 请求方式:Get
- 传参方式:路径参数(id)
r.GET("/community/page/get/:id", func(c *gin.Context) {
topicId := c.Param("id")
})
controller层
主要负责处理用户的输入和输出,不包含复杂的业务逻辑。
所以在这一步我们需要知道需要什么数据,以及处理后输出什么数据。
输入的数据在我们设计传参方式的时候就已经决定下来了,一个id就可以,不过需要使用标准strconv库,将字符串id转化为int64id,为后续传参做准备,并检测错误
输出的数据也需要一个结构体来表示
-
PageDate
- code(
int64 -1为false 0为true) - msg(
string 具体的错误信息) - data(
inerface{} 一个匿名的空接口,表示任意类型)
- code(
这里的重点是data的值,不过具体data值为多少,就需要交给service层处理
service层
service层包含更复杂的业务逻辑,处理数据的验证、计算、操作等
这里根据流程描述可以将业务逻辑划分为三步,检验传参,获取所需信息,打包
实现上述三个的方法都将其绑定为结构体方法,这样在值传递过程中,只需要一个实体就够了,更加方便
-
QueryPageInfoFlow
- topicId (
int64) - pageInfo (
*PageInfo) - topic (
*repository.Topic) - posts(
[]*repository.Post)
- topicId (
检验传参
根据业务逻辑,我们可以得知,传入参数为id,根据此id查询相关话题和回帖列表,因此id号不可能小于0,所以这里只需要判断一步就可以
获取所需信息
这里使用了并行,用 go 关键字开了两个goroutine,因为post数据和topic数据保存在两个不同的文件当中,可以并行读取,同时加锁,使两者异步转同步
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
//根据id,获取topic
}()
go func() {
defer wg.Done()
//根据id,获取post列表
}()
wg.Wait()
具体查询的方式也非常简单,topic直接根据id映射,post根据parent_id映射
将所得到的数据,赋值给结构体内部的topic和posts中
打包
为了使数据更加清楚,这里也定义了PageInfo的结构体
-
PageInfo
- Topic(
*repository.Topic) - PostList(
[]*repository.Post)
- Topic(
将QueryPageInfoFlow中PageInfo赋值,数据从QueryPageInfoFlow的topic和posts中来,整个功能便成功完成了
测试
主要对service层的业务进行测试,测试分两步,初始化和单元测试
初始化
加载数据所在文件夹
func TestMain(m *testing.M) {
repository.Init("../data/")
os.Exit(m.Run())
}
单元测试
主要测试下,返回是否为空,以及返回数量是否符合文件内的数量
assert.NotEqual(t, nil, pageInfo)
assert.Equal(t, 7, len(pageInfo.PostList))
结尾
这份课堂代码质量很高,从MVC三层架构,到业务逻辑的抽象归纳都做得非常好,尤其是结构体方法的运用和测试文件的书写,给我了很大的启发,对go有了更深一层次的了解,这里还有一份课后作业,添加append功能,将放在下次文章当中。