这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
课堂笔记
本堂课重点内容
- 第三方框架
- 小功能设计
- 功能设计路线
详细知识点介绍
需求设计
需求背景
- 支持回帖、点赞
- 对回帖可以进行回复
- 开发一个单页面设计服务端的小功能
需求描述
社区话题页面
- 展示话题(标题,文字描述)和回帖列表
- 暂不考虑前端页面实现,仅仅实现一个本地web服务
- 话题和回帖数据用文件存储
需求用例
面向浏览消费用户
- Topic -> 话题
- PostList -> 回帖历史
E-R
Topic<话题>
- id
- title
- content
- create_time
Post<帖子>
- id
- topic_id
- content
- create_time
Topic和Post的关系是一对多
分层结构
数据层Repostitory
- 数据Model,外部数据的增删改查
逻辑层Service
- 业务Entity,处理核心业务逻辑输出
视图层Controller
- 视图view,处理和外部的交互逻辑
组件工具
Gin高性能go web框架
Go Mod
go mod init
go get gopkg.in/gin-gonic/gin.v1@v1.3.0
代码开发
Repository
index
元数据 -> 索引
数据行 -> 内存map
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() {
text := scanner.Text()
var topic Topic
if err := json.Unmarshal([]byte(text), &topic); err != nil {
return err
}
topicTmpMap[topic.Id] = &topic
}
topicIndexMap = topicTmpMap
return nil
}
查询
索引:话题ID
数据:话题
使用symc.Once来实现高并发状态下只查询一次
var (
topicOnce sync.Once //高并发下只执行一次
topicDao *TopicDao
)
func NewTopicDaoInstance() *TopicDao {
topicOnce.Do(func() {
topicDao = &TopicDao{}
})
return topicDao
}
func (*TopicDao) QueryTopicDyId(id int64) *Topic {
return topicIndexMap[id]
}
var (
topicIndexMap map[int64]*Topic
postIndexMap map[int64]*Post
)
Service
实体
type TopicDao 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
func QueryPageInfo(topicIdStr string) *PageData {
topicId, err := strconv.ParseInt(topicIdStr, 10, 64)
if err != nil {
return &PageData{}
}
pageInfo, err := service.QueryPageInfo(topicId)
if err != nil {
return &PageData{}
}
return &PageData{}
}
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
}
}
实践练习例子
课后个人总结
- 需要熟练引用第三方的包来进行构建
- 搭建某个功能最好是采用第三方框架入手