GO语言工程实践课后作业 | 青训营

75 阅读2分钟

发布帖子功能与查询帖子不同,需要发送POST请求,也就需要在Server中绑定一个POST方法,同时还需要底层提供添加帖子的API以供调用。至于本地id的唯一性,可以简单的维护一个id最大值,每次新的id加一即可。最后需要注意Map的并发安全问题

现有版本基于内存的存储,因此本次课后实践依旧在此基础上进行,所以在现有版本基础上进行课后实践的开发工作

  1. 系统开始运行查询某个topic下的帖子列表:这个是已经提供的功能,需要注意的是topic和post数据是在系统启动的时候初始化的,查询某个topic的帖子就是直接从map中取出对应topic_id的post列表

    var(
        topicIndexMap map[int64]*Topic
        postIndexMap map[int64][]*Post
    )
    
    func (*TopicDao) QueryTopicById(id int64) *Topic {
        return topicIndexMap[id]
    }
    复制代码
    
  2. 为某个topic发布帖子:首先需要提供一个外部的接口,用于发布帖子

    r.POST( "/ community/post/pull", func(c *gin.Context) {
        postInfo := repository.Post{}
        if C.BindJSON(&postInfo) == nil {
            data := cotroller.(postInfo)
            C.JSON(200,data)
        }
    })
    err := r.Run()
    iferr != nil{
        return
    }
    复制代码
    
  3. repository层

    实现要求

    //实现一:发布帖子
    func ( postDao *PostDao) AddPost(postInfo Post) error {
        //实现二:本地id生成需要保证不重复、唯一性
        postDao.lock.Lock()
        defer postDao.lock.Unlock()
        num := int64(0)
        for _, list := range postIndexMap {
            num += int64(len(list))
        }
        postInfo.Id= num + 1
        postInfo.CreateTime = time.Now().Unix()
        
        
        //实现三:新的帖子Append到文件末尾,更新索引,注意Map的并发安全性问题
        filePath := ”./data/post"
        file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, 0666)
        iferr!=nil{
            fmt.Println("文件存储失败",err)
        }
        defer file.Close()
        write := bufio.NewWriter(file)
        data, err := json.Marshal(postInfo)
        iferr!=nil{
            return err
        }
        write.WriteString(string(data) + "\r\n")
        write.Flush()
        post IndexMap[postInfo.ParentId] = append(postIndexMap[postInfo.ParentId], &postInfo)
        return nil
    }
    复制代码
    
  • 因为postIndexMap[topic_id]对应着这个主题的所有帖子,但是数据是系统启动时去文件中读取的,在我们为文件追加一条post之后,并不会自动更新这个list,因此需要我们手动去追加帖子数据到postIndexMap[topic_id]末尾,才能做到内存数据与文件数据的一致性保证,从而不重启系统,重新获取列表就能查询到最新的帖子列表。因此不重启系统的情况下再次查询该topic的帖子列表需要更新
  • 这里提到的文件追加和map追加都涉及到并发安全性的问题,这里使用了互斥锁。
  • 关于自增id这里因为可以保证临界区的互斥访问,因此采用计数累加的形式实现帖子id唯一性