课后作业:
1. 支持发布帖子
2. 本地 ID 生成需要保证不重复、唯一性
3. Append 文件,更新索引,注意 Map 的并发安全问题
思路:采用json文件代替mysql来存储topic的键值对。
项目结构如下图

1.支持发布帖子
1.1 main.go中新增路由"community/topic/add"
r.POST("/community/topic/add", func(c *gin.Context) {
userId, _ := c.GetPostForm("user_id")
title, _ := c.GetPostForm("title")
content, _ := c.GetPostForm("content")
data := controller.AddTopic(userId, title, content)
c.JSON(200, data)
})
1.2 controller层中的AddTopic函数处理
func AddTopic(userIdStr, title, content string) *PageData {
userId, _ := strconv.ParseInt(userIdStr, 10, 64)
topicId, err := service.AddTopic(userId, title, content)
if err != nil {
return &PageData{
Code: -1,
Msg: err.Error(),
}
}
return &PageData{
Code: 0,
Msg: "发帖成功",
Data: map[string]int64{
"topic_id": topicId,
},
}
}
1.3 service层封装数据
func (f *AddTopicFlow) add() error {
topic := &repository.Topic{
Id: getOnlyId(),
UserId: f.userId,
Title: f.title,
Content: f.content,
CreateTime: time.Now(),
}
if err := repository.NewTopicDaoInstance().AddTopic(topic); err != nil {
return err
}
f.topicId = topic.Id
return nil
}
1.4 repository层将数据写入文件
func (*TopicDao) AddTopic(topic *Topic) error {
var topics = make([]Topic, 1)
file, err := ioutil.ReadFile("./json/topic.json")
if err != nil {
println("read file failed", err)
return err
}
var jsonErr error
if len(file) == 0 {
jsonErr = nil
} else {
jsonErr = json.Unmarshal(file, &topics)
}
if jsonErr == nil {
topics = append(topics, *topic)
data, err := json.MarshalIndent(topics, "", " ")
if err == nil {
err := ioutil.WriteFile("./json/topic.json", data, 0666)
if err == nil {
println("写入成功")
return nil
}
}
}
println("写入失败")
return err
}
1.5 运行结果
postman中返回结果

topic.json文件中的数据

2.保证id生成的唯一性:采用雪花算法来生成唯一的id
import "github.com/bwmarrin/snowflake"
func getOnlyId() int64 {
node, err := snowflake.NewNode(1)
if err != nil {
print("get id failed")
return -1
}
id := node.Generate()
return int64(id)
}
3.并发安全问题:使用读写锁来完成
3.1 在读文件的时候加锁,读完文件再解锁
rwLock.Lock()
file, err := ioutil.ReadFile("./json/topic.json")
rwLock.Unlock()
3.2 在写文件的时候加锁,写完文件再解锁
rwLock.Lock()
err := ioutil.WriteFile("./json/topic.json", data, 0666)
rwLock.Unlock()