这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
个人随笔,写的可能比较杂。
工程实践
- Goroutine 协程 提倡通过通信共享内存(而不是通过共享内存实现通信)
2.channel 通道 (通过通信共享内存)分为有缓冲通道和无缓冲通道
make (chan 元素类型,[缓冲大小])
无缓冲 make(chan int)
有缓冲 make(chan int, 2) (缓冲满了装不下,阻塞发送 -> 生产消费模型)
defer 用做延迟资源关闭
在Go语言中,通道是goroutine与另一个goroutine通信的媒介,并且这种通信是无锁的。换句话说,通道是一种允许一个goroutine将数据发送到另一个goroutine的技术
通过两个管道实现两个线程输出数据:
合并管道:
chan string这样的写法能够使用读写功能双向管道外,还可以创建出单向管道,如<-chan string只能从管道中读取数据,而chan<- string只能够向管道中写入数据。
单行<-XX 写法的意思
依次到并发的实例:
3.mutex 锁 (通过共享内存实现通信)
定义: var lock sync.Mutex 当需要对共享内存里进行修改
先 lock.Lock()
..
用完了 lock.Unlock()
4. WaitGroup 实现并发任务同步 (前面都用time.Sleep(time.Second) 实现暴力阻塞) sleep 也是为了防止主线程比子线程提前结束 也是在sync包下
Add(delta int) 计数器 +delta
Done() 计数器-1
Wait() 阻塞知道计数器为0
定义 : var wg sync.waitGroup wq.Add(delta: 5) // 因为要开五个携程
for i := 0; i < 5; i ++{ go func(j int) {
defer wg.Done() // 子协程任务结束, 计数器-1
hello(j) //自定义函数输出
}(i)
}
wg.Wait() // 进行阻塞
输出:4 0 1 2 3
依赖管理
(依赖:各种开发包,利用他人工具提高开发效率)
go的依赖管理的三个阶段 : GOPATH -> GO Vendor -> GO module
-
GOPATH 环境变量$GOPATH
项目代码直接依赖src下的代码 (go get 下载最新版本的包到src 目录下) 弊端无法实现package多版本控制
-
Go Vendor
项目目录下增加vendor 文件夹 项目依赖 (先找)govendor = > (再去)gopath 问题 无法控制依赖版本,因为都是依赖项目源码
-
Go Module 解决了问题
通过 go.mod 文件管理依赖包版本 通过 go get/go mod 指令工具管理依赖包 最终可以:定义版本规则和管理项目依赖关系
依赖管理三要素
1.配置文件 , 描述依赖了那些包,唯一去定位 go.mod
2. 中心仓库管理依赖库 (go.mod里) proxy
3. 本地工具 go.get / mod
(1). 依赖配置go.mod 托管到github上
require{
[Module Path][Version/Pseudo-version]
}
(2).依赖配置
语义化版本 如v1.2.3 (${MAJOR}.${MINOR}.${PATH})
基于commit 伪版本 v1.2.0-yyyymmddhhmmss-abchdefh1234 (同上版本-时间戳-hash校验码)
go.mod上一些关键词的解析:
(3). indirect
写法: 对于没有直接导入的依赖模块后标识“ //indirect” (正常是A->B 直接依赖 A->B->C a对c间接依赖)
(4).incompatible
写法: 对于之前仓库直接已经2+,没有go.mod文件且主版本2+的依赖会在后边写“+incompatible”
依赖分发
(5). 依赖分发-回源 直接关联去GIthub , SVN
(6).依赖分发-Proxy 稳定可靠 (当作者删除某个版本,仍然稳定) 在Develop 和 GItHub之间加一层Proxy
(7).依赖分发-变量GOPROXY
go.mod工具
(1)go.get example.org/pkg
@updata 默认
@ none 删除依赖
@v1.1.2 拉去特定版本
@23ddf 拉取特定commit
@master (指定分支)拉取分支最新commit
(2).go mod
init 初始化 创建go.mod 文件(项目开始步骤)
download 下载模块到本地(把所有依赖拉下来)
tidy 增加需要依赖删除不需要的(每次执行前可以运行一次,删一下)
测试
(用于避免事故的最后屏障)
-
回归测试
-
集成测试 对系统功能维度,对服务暴露的某个接口
-
单元测试 面对测试开发阶段,对单独函数模块做功能验证 (覆盖率最大,决定代码质量)
规则:
文件 都是xxx_test.go
测试函数 func TestXxx(XX *testing.T)
初始化逻辑放到 func TestMain(m *testing.M)
测试指令: go test [flag][packages]
开源的测试包
如 assert