# 课后作业
- 支持对话题发布回帖
- 回帖id生成需要保证不重复、唯一性。
- 新加回帖追加到本地文件,同时需要更新索引,注意Map的并发安全问题 这三个问题展开写
先回答第回帖的id要保证是不重复,唯一性,在数据库当中的话,我们可以使用自增主键,但是在高并发下的话,自增主键可能就会出现异常,所以一般来说都是使用外部的算法来进行生成主键,比如说Snowflake算法生成全局唯一的ID或者使用UUID(Universally Unique Identifier),这些办法生成的主键即使是在高并发的情况下也可以保证主键的唯一性。
我直接将Post结构体当中的ID换成了string,这样的话就可以在我们需要生成一个UUid时我们就可以直接new()一个新的id然后转化为string,这样就可以保证我们的回帖id是唯一的。
id := uuid.New().String()//使用UUID生成一个id
post.Id = id//将UUID生成的id赋值给Post的id
回帖需要追加到本地文件,一般来说我们都是使用数据库,将数据存储到数据库当中,但是课程暂时没有使用到,所以本地化选择是使用文本文件进行存储,并发的问题我们可以使用sync.Mutex添加互斥锁来保证我们的map的安全性,可以确保在同一时间只有一个goroutine可以修改postIndexMap。
func (d *PostDao) AddPost(post *Post) error {
// 加锁保证同时请求的并发安全
lock := sync.Mutex{}
lock.Lock()
defer lock.Unlock()
posts, ok := postIndexMap[post.ParentId]
if !ok {
return errors.New("post invalid, not exist parent id")
}
postIndexMap[post.ParentId] = append(posts, post)
filePath := "./homework/data/post"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return err
}
defer file.Close()
err = fileDataInsertPost(file, post)
if err != nil {
return err
}
return nil
}
func fileDataInsertPost(writer io.Writer, post *Post) error {
// 写入换行符
if _, err := writer.Write([]byte("\r\n")); err != nil {
return err
}
// 将帖子数据编码为JSON并写入文件
encoder := json.NewEncoder(writer)
if err := encoder.Encode(post); err != nil {
return err
}
return nil
}
总结
支持对话题回帖,实现其实就是新增一个回帖的方法,将回帖内容插入到我们的帖子表当中,唯一id的问题我们可以使用UUID生成一个唯一主键,还有就是将数据本地化,可以将数据写入到本地的文本文件,map的安全问题可以使用sync.Mutex加上互斥锁,保证并发安全。