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

82 阅读2分钟

本课的课后作业要求我们使该项目新增支持发布帖子的功能。 首先我们先针对数据层repository中的文件对项目代码进行修改 对于db_init中的initPostIndexMap函数的代码增加

if LastId < post.Id {  
LastId = post.Id  
}

由此来记录文件里最后的id,以便在发布帖子时以从小到大的顺序更新帖子的id。

接着,对于post文件新增函数AddPost来新增帖子

func (d *PostDao) AddPost(post *Post) error {  
    lock := sync.Mutex{}  
    lock.Lock()  
    posts, ok := postIndexMap[post.ParentId]  
    if !ok {  
        return errors.New("parentId not exist")  
    }  
  
    postIndexMap[post.ParentId] = append(posts, post)  
  
    err := d.InsertPost2Data("./data/", post)  
    if err != nil {  
        return err  
    }  
    lock.Unlock()  
    return nil  
}

首先先进行判断所新增帖子的ParenId是否存在,如没问题便将其加入到对应的map并将其写入到文件中。其中需要注意通过加锁来防止对map进行append操作时出现并发安全问题。

关于post文件中的InsertPost2Data函数

func (d *PostDao) InsertPost2Data(path string, post *Post) error {
    file, err := os.OpenFile(path+"post", os.O_WRONLY|os.O_APPEND, 0777)  
    defer file.Close()  
    if err != nil {  
        return err  
    }  
    writer := bufio.NewWriter(file)  
    data, err := json.Marshal(*post)  
    if err != nil {  
        return err  
    }  
    writer.Write(data)  
    writer.WriteString("\n")  
    writer.Flush()  
    return nil
}

首先该函数需要对post文件的尾部插入数据于是Openfile的flag选择读写和增添末尾的模式来打开post文件,并考虑性能决定以带缓冲的方式对文件进行写入,通过变量post进行序列化并将他写入缓冲流再利用Flush()进行刷新使缓冲中的内容写入到文件中。

以上就是为了发布帖子功能而对数据层进行的改动

接下来针对逻辑层service 新建publish-post文件

func (f *PublishPostFlow) Do() (int64, error) {  
    if err := f.checkParam(); err != nil {  
        return 0, err  
    }  
    if err := f.publishPost(); err != nil {  
        return 0, err  
    }  
    return f.id, nil  
}

以上是关于发布帖子service层中的流程编排,其中checkParam函数检查帖子的话题id是否合理,即大于0,publishPost则是通过repository进行发布帖子操作并同时更新LastId

service层实现完成,接下来就是controller层

func PublishPost(parent_idStr, content string) *PageData {  
  
    parent_id, err := strconv.ParseInt(parent_idStr, 10, 64)  
    if err != nil {  
        return &PageData{  
            Code: -1,  
            Msg: err.Error(),  
        }  
    }  
  
    pageInfo, err := service.PublishPost(parent_id, content)  
    if err != nil {  
        return &PageData{  
            Code: -1,  
            Msg: err.Error(),  
        }  
    }  
    return &PageData{  
    Code: 0,  
    Msg: "success",  
    Data: pageInfo,  
}

这里借助之前定义的PageData结构体作为view对象,通过code和msg打包业务状态信息,data承载业务实体信息

r.POST("/community/page/post", func(c *gin.Context) {  
//id, _ := c.GetPostForm("id")  
parent_id, _ := c.GetPostForm("parent_id")  
content, _ := c.GetPostForm("content")  
data := cotroller.PublishPost(parent_id, content)  
  
c.JSON(200, data)  
})

最后是server文件中的web引擎设置,通过path变量传递帖子的相关话题id和帖子的内容。过程包括初始化数据索引、初始化引擎配置、构建路由、启动服务。