这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
一、内容:
1.go的多线程编程
协程(coroutine) :又称微线程与子例程(或者称为函数)一样,协程(coroutine)也是一种程序组件。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。
和线程类似,共享堆,不共享栈,协程的切换一般由程序员在代码中显式控制。它避免了上下文切换的额外耗费,兼顾了多线程的优点,简化了高并发程序的复杂。
package concurrence
import (
"fmt"
"sync"
)
func hello(i int) {
println("hello world : " + fmt.Sprint(i))
}
func ManyGo() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
CSP:
通信共享内存
通过make()创建通道,for range会使通道缓存中的值被取出
package concurrence
func CalSquare() {
src := make(chan int)
dest := make(chan int, 3)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
println(i)
}
}
并发安全LOCK
背景:考虑一下count ++这样一个操作,看起来是一句代码,但其实底层经历了读取数据、更新cpu缓存、存入内存等一系列操作。所以我们代码的执行并不是原子性的,一旦多个协程并发执行就会可能出现严重的错误。
LOCK机制来保证操作的原子性
2.Go版本依赖管理
三要素:
配置文件 go.mod
与java 中pom.xml
module:用于定义当前项目的模块路径。
go:用于标识当前模块的 Go 语言版本,值为初始化模块时的版本,目前来看还只是个标识作用。
require:用于设置一个特定的模块版本。
exclude:排除一个特定的模块版本。
replace:用于将一个模块版本替换为另外一个模块版本。
module github.com/eddycjy/module-repo
go 1.13
require (
example.com/apple v0.1.2
example.com/banana v1.2.3
example.com/banana/v2 v2.3.4
example.com/pear // indirect # indirect 标识表示该模块为间接依赖
example.com/strawberry // incompatible
)
exclude example.com/banana v1.2.4
replace example.com/banana => example.com/fish
中心仓库管理依赖库 类比 java中的maven云仓库
本地工具 go get/mod 类比git
3.测试
单元测试: 软件中的最小可测试单元进行检查和验证,覆盖率越高越好
Mock: 减少对其他前置条件的依赖,自己生成
基准测试: 衡量代码性能
二、个人难点:
1.坑点
这次拉取项目,运行时报错了,通过日志发现是依赖包没有拉取成功的原因。
解决方法:
go env -w GOPROXY=https://goproxy.cn
三、课后个人总结:
本节课很好的从基础课又更深了一步,讲解了版本依赖管理和单元测试等,这些非常贴近实战开发的知识,为后期开发项目打下基础