Go 依赖管理+测试 | 青训营笔记

71 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

并发

协程Gorountine: 用户态,轻量级线程,栈MB级别 线程:内核态,线程跑多个携程,栈KB级别

协程使用: 在调用函数前加go关键字 -- 创建协程 阻塞:time.Sleep(time.Second) -- 子协程运行完前主协程不退出

协程之间的通信: 提倡通过通信共享内存而不是通过共享内存而实现通信 channel -- 通道 创建:make(chan 元素类型, [缓冲大小]) 无缓冲 -- 同步

并发安全 Lock:对临界区的控制保证并发安全

WaitGroup -- 计数器实现并发任务的同步 add(delta int) 计数器+delta (开启协程+1) done() 计数器-1 (执行结束-1) wait() 阻塞直到计数器为0 表明所有的并发任务都已完成(主协程)

var wg sync.WaitGroup
wq,Add(5)
for i := 0; i<5; i++ {
    go func(j int) {
        defer wg.Donr()
        hello(j)
    }(i)
}
wg.Wait()

依赖管理 Go Module

  • 通过 go.mod 文件管理依赖包版本
  • 通过 go get/ go mode 指令工具管理依赖包 终极目标:定义版本规则和管理项目依赖关系

三要素

  1. 配置文件,描述依赖 go.mod

依赖管理基本单元 : module XXX

原生库:go 1.16

单元依赖:require [module path][version/pseudo version]

依赖配置:

  • version:语义化版本 && 基于commit伪版本
  • indirect:间接依赖
  • incompatible:不兼容
  • 依赖图:选择最低的兼容版本
  1. 中心仓库管理依赖库 Proxy 依赖分发
  • Proxy:缓存原版本的软件内容(稳定 & 可靠)
  • 变量GOPROXY:服务站点URL列表,“direct”表示源站 GOPROXY = "proxy1.cn, proxy2.cn, direct"
  1. 本地工具 go get/mod go get example.org/pkg
  • @update 默认
  • @none 删除依赖
  • @v1.1.2 tag版本 语义版本
  • @23dfdd5 特定的commit
  • @master 分支的最新的commit go mod
  • init 初始化
  • download 下载模块到本地缓存
  • tidy 增加需要的依赖,删除不需要的依赖

测试

回归测试->集成测试(系统功能)->单元测试(单独的函数模块) 从左到右,覆盖率++,成本--

单元测试

规则:

  • 所有测试文件以_test.go结尾
  • 测试函数 funx TextXxx(*testing.T)
  • 初始化逻辑放到TestMain(m *testing.M) 中 Assert包:assert.Equal 代码覆盖率 测试分支相互独立、全面覆盖 测试单元粒度足够小,函数单一职责

依赖

外部依赖 =》 稳定(单元测试相互隔离)&幂等(重复运行测试结果一样)=》Mock

monkey:github.com/bouk/monkey

快速Mock函数: 打桩:打桩函数A去替换另一个源函数B

  • 为一个函数打桩
  1. Patch(target-B, replacement interface{}-A)
  2. Unpatch(target interface{}-A)
  • 为一个方法打桩

基准测试

对代码进行性能分析

项目实践

分层结构

  • 数据层:(repository)数据Model,外部数据的增删改查
  • 逻辑层:(service)业务Entity,处理核心业务的逻辑输出
  • 视图层:(controller)视图view,处理和外部的交互逻辑 组件工具:
  • Gin 高性能 go web 框架:github.com/gin-gonic/g…
  • Go Mod: go mod init go get gopok.in/gin-gonic/gin.v1@v1.3.0

repository - index

元数据 数据行 --> 索引 内存Map

var topicDao *TopicDao
//单例模式
var topicOnce sync.Once

func NewTopicDaoInstance() *TopicDao {
	topicOnce.Do(
		func() {
			topicDao = &TopicDao{}
		})
	return topicDao
}

func (*TopicDao) QueryTopicById(id int64) (*Topic, error) {
	var topic Topic
	err := db.Where("id = ?", id).Find(&topic).Error
	if err != nil {
		util.Logger.Error("find topic by id err:" + err.Error())
		return nil, err
	}
	return &topic, nil
}

service

流程:参数校验 -> 准备数据 -> 组装实体