这是我参与【第五届青训营】伴学笔记创作活动的第2天
一、并发与并行
可以充分发挥多核优势,高效运行。
1.并发
多线程程序在一个核的CPU上运行(时间片的切换)。
2.并行
多线程程序在多个核的CPU上同时运行。
二、协程与线程
1.协程
用户态,轻量级线程,栈KB级别。(创建与调度由go语言本身完成)。
2.线程
内核态,线程跑多个协程,栈MB级别。
3.协程的使用
快速打印Hello goroutine:0~Hello goroutine:4(快速意味开多个协程打印)
func hello(i int){
println("Hello goroutine:"+fmt.Sprint(i))
}
func HelloGoRoutine(){
for i := 0; i<5 ; i++{
go func(j int){
hello(j)
}(i)
}
time.Sleep(time.Second)
}
4.协程之间的通信CSP
提倡通过通信共享内存(临界区、互斥资源)而不是通过共享内存实现通信
5.通道Channel
通道的创建:make(chan 元素类型,缓冲大小)【有缓冲大小则说明有缓冲通道,无则说明没有】
无缓冲通道:保证发送与接收同步,故也称为同步通道
有缓冲通道:解决同步问题
6.Channel的具体使用
func CalSquare(){
src:=make(chan int)
dest:=make(chan int, 3)
go func(){
defer close(src)
for i:=0;i<0;i++{
src<-i
}
}()
go func(){
defer close(dest)
for i:=range src{
dest<=i*i
}
}()
for i:=range dest{
println(i)
}
}
7.并发安全Lock
var(
x int64
lock sync.Mutex
)
func addWithLock(){
for i:=0;i<2000;i++{
lock.Lock()
x+=1
lock.Unlock()
}
}
func addWithoutLock(){
for i:=0;i<2000;i++{
x+=1
}
}
8.WaitGroup
实现并发任务的同步,实质是内部维护一个计数器。
方法:
Add(delta int) 计数器+delta(开启协程+1)
Done() 计数器-1(执行结束-1)
Wait() 阻塞直到计数器为0(主协程)
func ManyGoWait(){
var wg sync.WaitGroup
wg.Add(delta:5)
for i:=0;i<5;i++{
go func (j int)
defer wg.Done()
hello(j)
}
}
三、依赖管理
其他:API应用程序编程接口:是一些预先定义的函数,目的是提供应用程序与开发人员基于某个软件或硬件得以访问一组进程能力,不需直接访问源码,或内部工作机制细节
SDK:软件开发工具包
1.GO依赖管理演进
GOPATH->GO VENDOR->GO MODULE
(1)GOPATH[GO项目工作区]
bin 项目编译的二进制文件
pkg 项目编译中间产物,加速编译
src 项目源码
项目代码直接依赖src下的代码
go get 下载最新版本的包到src目录下
弊端:无法实现pakage的多版本控制
(2)GO VENDOR
项目目录下增加vendor文件,所有依赖包副本形式放在$projectroot/vendor
依赖寻址方式:vendor->gopath
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个pakage依赖的冲突问题
弊端:也是依赖源码;无法控制依赖的版本;更新项目又可能出现依赖冲突,导致编译出错
(3)GOMODULE
通过go.mod文件管理依赖包版本
通过go get/go mod指令工具管理依赖包
终级目标:定义版本规则和管理项目依赖关系
2.依赖管理三要素
(1)配置文件,描述依赖 go.mod
module example/project/app
go 1.16
require(
...
)
(2)中心仓库管理依赖库 Proxy
依赖分发-Proxy(服务站点,会缓存源站中软件内容,缓存软件版本不会改变)
依赖分发-变量GOPROXY
GOPROXY="https://proxy1.cn,https://proxy2.cn,direct"
服务站点列表,“direct”表示源站(若前面站点无依赖,会回源到第三方代码平台)
gomod通过GOPROXY环境变量来控制proxy的配置的
(3)本地工具 go get/mod