GO进阶| 青训营笔记

34 阅读1分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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依赖的冲突问题