简单实现GO工程进阶课课后实践题 | 青训营笔记

66 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第二天,在本日的学习中,简单了解了一些GO编程的工程基础。下面将基于上课的代码,简单修改完成课后实践题。

具体过程

首先我们分析一下Post的格式:

type Post struct {
	Id         int64  `json:"id"`
	ParentId   int64  `json:"parent_id"`
	Content    string `json:"content"`
	CreateTime int64  `json:"create_time"`
}

可以发现,Id是自增长的,ParentId是基于当前话题页的,Content是用户输入的,而CreateTime则应该基于当前时间。也就是说,IdCreateTime应该由程序自动填充,而另外两个则要基于前端的Post请求参数。

为此,我们简单实现一个处理Post请求的路由:

r.POST("/community/page/post/:id", func(c *gin.Context) {
	// 数据处理部分:
	content := c.PostForm("content")
	create_time := time.Now().Unix()
	parent_id, err := strconv.ParseInt(c.Param("id"), 10, 64)
	id := 1145 //暂时如此

        // 暂不处理错误路由部分
	if err != nil {
		fmt.Println("请求路径有误")
		return
	}
	newPost := repository.Post{Id: int64(id), ParentId: parent_id, Content: content, CreateTime: create_time}

	//先测试传输是否正确
	fmt.Println(newPost)
})

然后可以用curl命令模拟前端接收的Post请求:

curl -X POST -d "content=just_a_test" "http://127.0.0.1:8080/community/page/post/2"

得到结果接收正确:

image.png

然后实现一下将新数据加入map和文件的数据层函数:

func AddPostIndexMap(filePath string, newInfo *Post) error {
	open, err := os.OpenFile(filePath+"post", os.O_APPEND|os.O_RDWR, 0660)
	if err != nil {
		return err
	}
	defer open.Close()
	// 使用最简单的锁保证并发安全
	lock.Lock()
	posts, ok := postIndexMap[newInfo.ParentId]
	if !ok {
		postIndexMap[newInfo.ParentId] = []*Post{newInfo}
	} else {
		posts = append(posts, newInfo)
		postIndexMap[newInfo.ParentId] = posts
	}

	json_string, err := json.Marshal(newInfo)
	if err != nil {
		return err
	}
	open.WriteString("\n" + string(json_string))
	
	lock.Unlock()

	return nil
}

在上面的代码中,加入map操作可以类比原有的initPostIndexMap函数,而写入文件则可以考虑直接使用WriteString函数。整体的并发安全只使用了最简单的锁,显然该做法是简单粗暴且较为费时的,后续会考虑改进。

再写一个简单的服务层函数用于调用上面的函数,在视图层调用即可:

func AddPostInfo(filePath string, newInfo *repository.Post) {
	go repository.AddPostIndexMap(filePath, newInfo)
}

最后,我们还剩下回帖ID的唯一自增。可以考虑在数据层加入一个计数器用于记录当前到第几条回帖信息,并在初始化时顺便初始化计数器即可。

测试并发性,这里采用最简单的串行测试,仅仅使用批处理命令循环发送post请求,可以得到正确的结果:

for /l %%i in (1,1,100) do (
    curl -X POST -d "content=just_a_test" "http://127.0.0.1:8080/community/page/post/2"
)

image.png

image.png