这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。 课程内容相关代码链接 取V0版本 我是直接fork到自己Github,然后进行版本切换和修改
一、Git命令熟悉
运行该命令即可克隆代码
(如果只想保留最新的文件而不要历史版本的文件,可以用git pull --dpeth 1命令,即“浅克隆”:)
git clone -b v5.2.0 --depth=1 https://github.com/Moonlight-Zhao/go-project-example/
创建新分支命令:git branch xxx
切换分支命令:git checkout xxx
查看当前分支:git branch
想提交代码到自己的Github仓库上时:
git add *
git commit -m "commit"
git push origin xxx (xxx为目标的分支名)
二、实现新功能
我的Github代码:github.com/yhmain/go-p… 项目整体架构:
1. Postman测试工具(谷歌浏览器插件)
为了模拟post请求调试
界面截图如下:
2. 本地ID生成需要保证不重复、唯一性
雪花ID:snowflake是Twitter开源的分布式ID生成算法,结果是64bit的Long类型的ID,有着全局唯一和有序递增的特点,利用时间戳生成。
在service层导入包:idworker "github.com/gitstliu/go-id-worker"
基于SnowFlake算法,跨数据中心的全局分布式ID生成器。
应用代码如下:
注意init是个很特殊的函数,用于package的初始化,先于main函数自动执行。
var idGen *idworker.IdWorker
//ID生成器的初始化
func init() {
idGen = &idworker.IdWorker{}
//WORKERID位数 (用于对工作进程进行编码)
//数据中心ID位数 (用于对数据中心进行编码)
idGen.InitIdWorker(1, 1)
}
func xxx(){
...
id, err := idGen.NextId() //生成新ID
...
}
3. Append文件,更新索引,注意 Map 的并发安全问题
sync包实现了两种锁:
- Mutex:互斥锁
- RWMutex:读写锁,RWMutex 基于Mutex实现
Mutex
- 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex
- 适用于读写不确定,并且只有一个读或者写的场景
RWMutex
- 锁占用的情况下会阻止写,不会阻止读,多个 goroutine 可以同时获取读锁
- 写锁会阻止其他 goroutine(无论读和写)进来,整个锁由该 goroutine 独占
- 适用于读多写少的场景
这里我采用的是读写锁,代码如下:
//向文件/数据库中插入新发布的帖子
func (*PostDao) InsertNewPost(post *Post) error {
//0600 0rw-------
open, err := os.OpenFile("./data/post", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
defer open.Close()
postStr, _ := json.Marshal(post) //序列号为json格式
//写入文件时需要string
//注意windows中回车换行符
if _, err = open.WriteString(string(postStr) + "\n"); err != nil {
return err
}
//更新Map时考虑并发安全性问题
rwMutex.Lock()
postList, ok := postIndexMap[post.ParentId]
//若字典中不存在该主题ID,则新建
if !ok {
postIndexMap[post.ParentId] = []*Post{post}
} else {
postList = append(postList, post)
postIndexMap[post.ParentId] = postList
}
rwMutex.Unlock()
return nil
}
三、测试
- 单元测试
- Mock测试
- 基准测试