GO语言工程实践课后作业:实现思路、代码以及路径记录(二) | 青训营

86 阅读3分钟

书接上回

课后作业

  1. 支持对话题发布回帖。
  2. 回帖id生成需要保证不重复、唯一性。
  3. 新加回帖追加到本地文件,同时需要更新索引,注意Map的并发安全问题 

新加回帖追加到本地文件,同时需要更新索引,注意Map的并发安全问题  这个暂时没有实现

我搜寻了一些文章后发现 使用sync.RWMutex 在map并发读写时保证安全 这个策略可以实现,需要重写一下 repository.topic里边的topic的索引结构,封装一个包含 map + sync.RWMutex的结构体,具体修改过的repository.topic如下:

package repository

import (
	"sync"
)

type Topic struct {
	Id         int64  `json:"id"`
	Title      string `json:"title"`
	Content    string `json:"content"`
	CreateTime int64  `json:"create_time"`
}
type TopicDao struct {
}

var (
	topicDao  *TopicDao
	topicOnce sync.Once
)

func NewTopicDaoInstance() *TopicDao {
	topicOnce.Do(
		func() {
			topicDao = &TopicDao{}
		})
	return topicDao
}
func (*TopicDao) QueryTopicById(id int64) *Topic {
	return topicIndexMap[id]
}

另外,回帖id另有一种写法是

// 获取读写锁
rwMutex.Lock()

// 从 postIndexMap 中获取指定 ParentId 对应的 postList
postList, ok := postIndexMap[post.ParentId]
if !ok {
    // 如果不存在对应的 postList,则创建一个新的列表并将当前 post 加入其中
    postIndexMap[post.ParentId] = []*Post{post}
} else {
    // 如果存在对应的 postList,则将当前 post 加入到列表末尾
    postList = append(postList, post)
}

// 将更新后的 postList 赋值给 postIndexMap[post.ParentId]
postIndexMap[post.ParentId] = postList

// 释放读写锁
rwMutex.Unlock()

在实现发布帖子功能时,为了确保数据的一致性和并发安全,我们需要使用读写锁(rwMutex)来保护对postIndexMap的访问。读写锁允许多个读操作同时进行,但在写操作时会阻塞其他读写操作,从而确保数据的完整性。

首先,我们需要在Server中绑定一个POST方法,用于处理用户发布的帖子。这个方法需要接收一个包含帖子内容和其他相关信息的请求体,然后将帖子添加到postIndexMap中。在添加帖子之前,我们需要获取写锁,以防止其他读写操作同时修改postIndexMap。添加完成后,释放写锁,允许其他读写操作继续进行。

其次,我们需要提供底层的添加帖子API,以便调用者可以方便地创建和发布帖子。这个API可以是一个HTTP接口,客户端通过发送POST请求来调用它。在API内部,我们可以使用上面提到的POST方法来处理请求,并将帖子添加到postIndexMap中。

关于本地id的唯一性问题,我们可以简单地维护一个id最大值,每次新的id加一即可。这样,即使在高并发的情况下,每个帖子也可以有一个唯一的id。当然,这种方法可能会导致id溢出的问题,但在这个场景下,我们并不需要考虑这个问题,因为我们并不涉及高并发大数据等性能问题。

最后,我们需要注意Map的并发安全问题。虽然我们这里使用了读写锁来保证并发安全,但仍然需要注意一些潜在的问题。例如,如果在获取读锁后立即释放锁,然后又立即尝试获取锁,可能会导致死锁等问题。为了避免这种情况,我们可以使用一些工具或库来帮助我们管理锁的生命周期,或者使用更复杂的同步机制来确保并发安全。

总之,在使用读写锁保护对postIndexMap的访问时,我们需要确保在写操作时获取写锁,并在完成写操作后释放锁。同时,我们还需要提供底层的添加帖子API,并注意Map的并发安全问题。通过这些措施,我们可以确保发布帖子功能的正确性和安全性。

今天没有课的话(本来想水一下下一节的内容【doge】),就偷下懒,就这样吧