Go语言工程实践(二) | 青训营笔记

122 阅读2分钟

Go语言工程实践(二) | 青训营笔记

这是我参与「第三届青训营 -后端场」笔记创作活动的的第二篇笔记。

项目实战

需求设计

需求描述

  • 展示话题和回帖列表
  • 暂不考虑前端页面实现,仅仅实现一个本地web服务
  • 话题和回帖数据用文件储存

需求用例

1652172127(1).png

ER图

1652172163(1).png

分层结构

1652172257(1).png

代码开发

Repository

type Topic struct {
   Id         int64  `json:"id"`
   Title      string `json:"title"`
   Content    string `json:"content"`
   CreateTime int64  `json:"create_time"`
}
type Post struct {
   Id         int64  `json:"id"`
   ParentId   int64  `json:"parent_id"`
   Content    string `json:"content"`
   CreateTime int64  `json:"create_time"`
}

Repository-index

var (
   topicIndexMap map[int64]*Topic
   postIndexMap  map[int64][]*Post
)
  • 初始话题数据索引
func initTopicIndexMap(filePath string) error {
   open, err := os.Open(filePath + "topic")//打开文件
   if err != nil {
      return err
   }
   scanner := bufio.NewScanner(open)
   topicTmpMap := make(map[int64]*Topic)
   for scanner.Scan() {//Scan()默认对每行进行读写
      text := scanner.Text()//Text()将Scan()读到的元素变为String
      var topic Topic
      if err := json.Unmarshal([]byte(text), &topic); err != nil {//Unmarshal进行反序列化,并将结果指向topic
         return err
      }
      topicTmpMap[topic.Id] = &topic
   }
   topicIndexMap = topicTmpMap
   return nil
}

初始回帖的数据索引可以采用相同的方式

Repository-查询

var (
   topicDao  *TopicDao
   topicOnce sync.Once//sync.Once 是 Go 标准库提供的使函数只执行一次的实现,常应用于单例模式,例如初始化配置、保持数据库连接等
)
func NewTopicDaoInstance() *TopicDao {
   topicOnce.Do(
      func() {
         topicDao = &TopicDao{}
      })
   return topicDao
}
func (*TopicDao) QueryTopicById(id int64) *Topic {
   return topicIndexMap[id]
}

Service

type PageInfo struct {
   Topic    *repository.Topic
   PostList []*repository.Post
}
func (f *QueryPageInfoFlow) Do() (*PageInfo, error) {
   if err := f.checkParam(); err != nil {
      return nil, err
   }
   if err := f.prepareInfo(); err != nil {
      return nil, err
   }
   if err := f.packPageInfo(); err != nil {
      return nil, err
   }
   return f.pageInfo, nil
}

Controller

type PageData struct {
   Code int64       `json:"code"`
   Msg  string      `json:"msg"`
   Data interface{} `json:"data"`
}
func QueryPageInfo(topicIdStr string) *PageData {
   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,
   }

}

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) {
      topicId := c.Param("id")
      data := cotroller.QueryPageInfo(topicId)
      c.JSON(200, data)
   })
   err := r.Run()
   if err != nil {
      return
   }
}

func Init(filePath string) error {
   if err := repository.Init(filePath); err != nil {
      return err
   }
   return nil
}