go工程进阶-社区话题页面后端实现 | 青训营笔记

129 阅读3分钟

这是我参与[第五届青训营]伴学笔记创作活动的第2天

一、需求设计

  • 1)需求描述

     社区话题页面
     展示话题(标题、文字描述)和回帖列表
     不考虑前端页面的实现,仅实现一个本地web服务
     话题和回帖数据用文件存储
    
  • 2)需求用例

image.png

  • 3)ER图

image.png

  • 4)分层结构

image.png

             数据层:数据Model,外部数据的增删改查
             逻辑层:业务Entity,处理核心业务逻辑输出
             视图层:视图view,处理和外部的交互逻辑

二、代码开发

  • 1)设计数据结构体

     1.主要通过定义结构体格式化json内容,将其以键值对的方式储存在内存Map中
     //格式化元数据——帖子
     type Post struct {
         Id         int64  `json:"id"`
         ParentId   int64  `json:"parent_id"`
         Content    string `json:"content"`
         CreateTime int64  `json:"create_time"`
     }
     ​
     //格式化元数据——话题
     type Topic struct {
         Id         int64  `json:"id"`
         Title      string `json:"title"`
         Content    string `json:"content"`
         CreateTime int64  `json:"create_time"`
     }
     ​
     ​
     //索引
     var (
         //话题
         topicIndexMap map[int64]*Topic
         //对应话题的所有帖子
         postIndexMap  map[int64][]*Post
     )
     ​
     2·逻辑层的实体内容
     //页面信息结构体
     type PageInfo struct {
         Topic    *repository.Topic
         PostList []*repository.Post
     }
     ​
     //对应话题内容及其所有帖子
     type QueryPageInfoFlow struct {
         topicId  int64
         pageInfo *PageInfo
     ​
         topic   *repository.Topic
         posts   []*repository.Post
     }
     ​
     3·控制层
     //返回响应内容
     type PageData struct {
         Code int64       `json:"code"`
         Msg  string      `json:"msg"`
         Data interface{} `json:"data"`
     }
    

    主要思路是:先根据json格式创建相应的结构体,然后将json字符串序列化成go结构体。这一步是对归纳话题以及根据话题对所有帖子进行分类;然后根据项目要求——展示话题(标题、文字描述)和回帖列表,创建一个结构体,储存对应话题的内容以及其所包含的所有帖子;将其作为响应返回给用户。

  • 2)核心实现方法

    Router

     func main() {
         //初始化数据索引
         if err := Init("./data/"); err != nil {
             os.Exit(-1)
         }
         //初始化引擎配置
         r := gin.Default()
         //构建路由
         r.GET("/community/page/get/:id", func(c *gin.Context) {
             //获取请求页中的id
             topicId := c.Param("id")
             //把这个id作为索引去查询相应的内容
             data := cotroller.QueryPageInfo(topicId)
             c.JSON(200, data)
         })
         //启动服务
         err := r.Run()
         if err != nil {
             return
         }
     }
    

    这部分代码主要是初始化数据和解析请求,取得对应的话题id,然后将其传给Controller包的查询函数

    Controller

     func QueryPageInfo(topicIdStr string) *PageData {
         //将所传入的数字字符串转化为64位十进制的整型
         topicId, err := strconv.ParseInt(topicIdStr, 10, 64)
         if err != nil {
             return &PageData{
                 Code: -1,
                 Msg:  err.Error(),
             }
         }
         //根据话题索引号查询相应的内容
         pageInfo, err := service.QueryPageInfo(topicId)
         if err != nil {
             return &PageData{
                 Code: -1,
                 Msg:  err.Error(),
             }
         }
         return &PageData{
             Code: 0,
             Msg:  "success",
             Data: pageInfo,
         }
     ​
     }
     ​
    

    这部分代码主要是解析传入的数字字符串,然后调用Service包的方法查找相应的数据

    Service

     func (f *QueryPageInfoFlow) prepareInfo() error {
         //获取topic信息
         var wg sync.WaitGroup
         wg.Add(2)
         go func() {
             defer wg.Done()
             //返回topicId对应的话题
             topic := repository.NewTopicDaoInstance().QueryTopicById(f.topicId)
             f.topic = topic
         }()
         //获取post列表
         go func() {
             defer wg.Done()
             //返回topicId对应话题下的帖子
             posts := repository.NewPostDaoInstance().QueryPostsByParentId(f.topicId)
             f.posts = posts
         }()
         wg.Wait()
         return nil
     }
    

    这部分代码主要是根据话题id号获取对应的话题内容以及该话题下的所有帖子

三、测试运行

首先go run server.go

然后在Terminal中输入:curl http://localhost:8080/community/page/get/2

运行结果截图如下:

image.png

四、总结

在进行项目代码理解之前应熟悉需求,必要时需要在理解过程将代码和项目需求对应理解。

开发思路和代码执行思路是相反的过程,结合这两个方向可以对项目有更进一步的理解。

共勉!