这是我参与【第五届青训营】笔记创作的第2天,今天学习的是go依赖管理和测试,还有一个模仿话题和回帖的web项目
第一章 Go的依赖管理
第一节 依赖管理
1.1 背景
也就是相当于java的依赖引入,因为有的功能已经被其他人集成了,现在的开发已经不能仅仅只局限于单一的依赖了,这就需要引入依赖管理
1.2 GOPATH
介绍 : 项目的源码直接放在src下,现在的最新的依赖包也放在src下
弊端 : 无法进行依赖的多版本控制,导致因为依赖的升级,使得有些方法消失了,但是不能继承上一版本,这就使得代码变动变大
1.3 GO Vender
通过每个项目引入一份依赖的副本,
解决了多个项目需要同一个package依赖的冲突问题。
依赖寻址是先从vender中找,然后再去找GOPATH
弊端
1.4 Go Module
可以类比java的maven依赖管理
依赖配置 :
原生库,就是go语言的版本
单元依赖,就是前面是path,后面是版本
版本号介绍
关键字 :
indirect 就是间接依赖
主版本
依赖的版本选择 : 最低的兼容版本
依赖分发 :
不能将依赖源码直接放在github仓库等第三方仓库中,这样会不稳定,且加大了仓库的压力
这时就需要一个代理来解决这个问题,第三方仓库仅仅只是指向了这个代理,不进行源码的存储管理
第二章 测试和web项目
第一节 单元测试
1.1 介绍
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。
1.2 规则
1.3 例子
- 输入 : 空
- 预期输出 : “Tom”
- 结果 : 测试失败,不满足预期输出结果
1.4 覆盖率
单元测试的覆盖率是一个测试用例通过了多少行代码:
如本案例中输入的70,就覆盖了三行代码
第二节 基准测试
2.1 介绍
基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。
第三节 项目实践
3.1 需求分析
浏览消费用户
ER图
3.2 分层结构
3.3 组件工具
3.4 使用go mod下载gin依赖
- 设置参数
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
- 安装gin
mkdir gin
cd gin
go mod init gin
go get -u github.com/gin-gonic/gin
- 创建hello.go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
- 测试连接
3.5 数据层设置
话题和文章的存储结构
初始化话题数据的函数
func initTopicIndexMap(filePath string) error {
// 读取文件
open, err := os.Open(filePath + "topic")
if err != nil {
return err
}
// 转换为scanner
scanner := bufio.NewScanner(open)
// 创建话题map
topicTmpMap := make(map[int64]*Topic)
// 从scanner中扫描,读取每一行的text
for scanner.Scan() {
text := scanner.Text()
var topic Topic
// 将json文本转化为topic结构体
err := json.Unmarshal([]byte(text), &topic)
if err != nil {
return err
}
// 设置id和话题对应
topicTmpMap[topic.Id] = &topic
}
// 赋值
topicIndexMap = topicTmpMap
return nil
}
实现查询操作 : 通过topicId 查询话题
func (*TopicDao) QueryTopicById(id int64) *Topic {
return topicIndexMap[id]
}
3.6 Service层
这里是调用数据层的接口方法,查询获取到话题和回帖信息,然后封装成PageInfo结构体,返回上层调用
func (f *QueryPageInfoFlow) prepareInfo() error {
//获取topic信息
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
topic := repository.NewTopicDaoInstance().QueryTopicById(f.topicId)
f.topic = topic
}()
//获取post列表
go func() {
defer wg.Done()
posts := repository.NewPostDaoInstance().QueryPostsByParentId(f.topicId)
f.posts = posts
}()
wg.Wait()
return nil
}
3.7 Controller层
实现的是对service传来数据的转化,作为视图的json形式传出去
type PageData struct {
Code int64 `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
func QueryPageInfo(topicIdStr string) *PageData {
topicId, err := strconv.ParseInt(topicIdStr, 10, 64)
if err != nil {
return &PageData{
Code: -1,
Msg: err.Error(),
}
}
pageInfo, err := service.QueryPageInfo(topicId)
if err != nil {
return &PageData{
Code: -1,
Msg: err.Error(),
}
}
return &PageData{
Code: 0,
Msg: "success",
Data: pageInfo,
}
}
3.8 Main主启动
-
初始化数据索引
-
初始化引擎配置
-
构建路由
-
启动服务
func main() {
if err := Init("./data/"); err != nil {
os.Exit(-1)
}
r := gin.Default()
r.GET("/community/page/get/:id", func(c *gin.Context) {
topicId := c.Param("id")
data := cotroller.QueryPageInfo(topicId)
c.JSON(200, data)
})
err := r.Run()
if err != nil {
return
}
}