go依赖管理和测试 | 青训营笔记

64 阅读4分钟

这是我参与【第五届青训营】笔记创作的第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 例子

  1. 输入 : 空
  2. 预期输出 : “Tom”
  3. 结果 : 测试失败,不满足预期输出结果

1.4 覆盖率

单元测试的覆盖率是一个测试用例通过了多少行代码:

如本案例中输入的70,就覆盖了三行代码

第二节 基准测试

2.1 介绍

基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。

第三节 项目实践

3.1 需求分析

浏览消费用户

ER图

3.2 分层结构

3.3 组件工具

3.4 使用go mod下载gin依赖

  1. 设置参数
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
  1. 安装gin
mkdir gin 
cd gin
go mod init gin
go get -u github.com/gin-gonic/gin
  1. 创建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")
}
  1. 测试连接

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主启动

  1. 初始化数据索引

  2. 初始化引擎配置

  3. 构建路由

  4. 启动服务

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
    }
}