这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
一. 并发与并行
并发在宏观上是同时进行的,在微观上是多个线程程序在一个核的CPU上运行,表现为CPU的分时使用。
并行是多线程程序在多个核的CPU上运行。
Go语言可以充分发挥多核优势来高效运行。
可以通过多线程来快速实现程序,下面为使用多线程快速打印:
import (
"fmt"
"time"
)
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)
}
Go也可以通过通信共享内存信息。
可使用make来构建通道,通道分为无缓冲通道和有缓冲通道。示例如下:
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)
}
}
src为无缓冲通道,dest为3个缓冲区的有缓冲通道,可用来模拟消费者消费。
而Go实现互斥可使用WaitGroup,Add(delta int) 会使得计数器+delta,Done()会使计数器-1 。
也可使用互斥来实现快速打印:
import (
"sync"
"time"
)
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
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
二. 依赖管理
GOPATH: 是一个环境变量,其中有三个部分:
- bin:项目编译的二进制文件
- pkg:项目编译的中间产物,加速编译
- src:项目源码,项目代码直接依赖src下的代码
go get下载最新版本的包到src目录下
存在的弊端:无法实现package的多版本控制
GO Vender:项目目录下增加vender文件,所有依赖包副本形式放在$ProjectRoot/vender
依赖寻址方式:vender -> GOPATH
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题