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

84 阅读3分钟

💌 这是我参与「第五届青训营」伴学笔记创作活动的第 4 天。

🧡 本堂课重点内容

  • 项目实战:通过项目需求、需求拆解、逻辑设计、代码实现感受真实的项目开发。

🧡 实战项目

需求设计

💌 完成社区话题页面的后端部分,具体要求:

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

💌 对于浏览用户来说,请求的页面内容包括两个实体:话题内容 Topic 和回帖列表 PostList,ER 图如下,为一对多的关系: image.png

代码开发

💌 Go 开发的项目同样有如下分层结构: image.png 数据层:外部数据的增删改查。
逻辑层:处理核心业务逻辑输出。
视图层:处理和外部的交互逻辑。
💌 组件工具

  • 高性能 go web 框架 Gin:gin-gonic/gin
  • Go Mod 下载 gin 依赖
go mod init
go get gopkg.in/gin-gonic/gin.v1@v1.3.0

image.png 💌 接下来我们来学习如何编写一个完整的项目功能,代码如下:
Moonlight-Zhao/go-project-example at V0 (github.com)
🍠 Repository 数据层实现查询操作,将文件中数据行映射到内存 Map 中构建索引,初始化话题索引函数:initTopicIndexMap,初始化回帖索引函数:initPostIndexMap,通过索引就可以快速定位数据行,避免进行全表扫描。

// 索引
var (
   topicIndexMap map[int64]*Topic
   postIndexMap  map[int64][]*Post
)
// Topic实体的结构体
type Topic struct {
   Id         int64  `json:"id"`
   Title      string `json:"title"`
   Content    string `json:"content"`
   CreateTime int64  `json:"create_time"`
}
// Post实体的结构体
type Post struct {
   Id         int64  `json:"id"`
   ParentId   int64  `json:"parent_id"`
   Content    string `json:"content"`
   CreateTime int64  `json:"create_time"`
}
// 根据索引查询 Topic 内容
func (*TopicDao) QueryTopicById(id int64) *Topic {
   return topicIndexMap[id]
}
// 根据索引查询 Post 列表
func (*PostDao) QueryPostsByParentId(parentId int64) []*Post {
	return postIndexMap[parentId]
}

🍠 Service 逻辑层实现流程:

  • 参数校验checkParam:对传入的 id 进行非法校验。
  • 准备数据prepareInfo:拿到从数据层传来的数据,可以并行处理。
  • 组装实体packPageInfo:组装页面中包含的实体信息。

🍠 Controller 视图层实现流程:

  • 构建 View 对象
type PageData struct {
   Code int64       `json:"code"`
   Msg  string      `json:"msg"`
   Data interface{} `json:"data"`
}
  • 业务错误码
// 错误返回
return &PageData{
   Code: -1,
   Msg:  err.Error(),
}
// 正确返回
return &PageData{
    Code: 0,
    Msg:  "success",
    Data: pageInfo,
}

🍠 Gin 搭建外部框架

  • 初始化数据索引:通过遍历两个实体数据生成索引。
if err := Init("./data/"); err != nil {
   os.Exit(-1)
}
  • 初始化引擎配置
r := gin.Default()
  • 构建路由:获取 URL 路由,拿到话题 id 传给视图层,将查询内容以 JSON 格式返回,传给前端。
r.GET("/community/page/get/:id", func(c *gin.Context) {
   topicId := c.Param("id")
   data := controller.QueryPageInfo(topicId)
   c.JSON(200, data)
})
  • 启动服务
err := r.Run()

测试运行

💌 运行 main 函数,暴露 8080 端口,查看查询结果。 image.png

🧡 课后总结

💌 本堂课学习了 Go 项目开发的三层框架以及具体开发流程,实现了简单的话题页面查询操作,对后续大项目的搭建非常有帮助,课后还会尝试其他功能的开发。