Go的进阶学习 | 青训营笔记

35 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第2天


1.锁Lock

Go语言包中的 sync 包提供了两种锁类型:sync.Mutex为互斥锁和sync.RWMutex为读写互斥锁。而Mutex是最简单的一种锁类型,同时也比较暴力,当一个goroutine获得了Mutex后,其他goroutine就只能等到这个goroutine释放该Mutex。
下面代码为Mutex的实例:

package main

import (
    "fmt" 
    "sync" 
    "time" 
) 
// 除了使用channel实现同步之外,还可以使用Mutex互斥锁来实现同步。 
    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)
    fmt.Println("WithoutLock :", x) 
    x = 0 
    for i := 0; i < 5; i++ {
    go AddWithLock() 
} 
    time.Sleep(time.Second) 
    fmt.Println("WithLock :", x)
} 
func main() { 
    Add()
}
// 输出: WithoutLock : 8986 WithLock : 10000

2.线程同步 WaitGroup

其意义:用于线程同步,WaitGroup等待一组线程集合完成,才会继续向下执行。主线程 (goroutine) 调用 Add 来设置等待的线程(goroutine)数量。 然后每个线(goroutine)运行,并在完成后调用Done。同时,Wait用来阻塞,直到所有线程(goroutine)完成才会向下执行。 如下面代码所示:

package main 

import ( 
     "fmt"
     "sync" 
 ) 
func HelloPrint(i int) { 
    fmt.Println("Hello WaitGroup :", i) 
} 
func ManyGoWait() { 
    var wg sync.WaitGroup 
    wg.Add(5) 
    for i := 0; i < 5; i++ { 
    go func(j int) { 
    defer wg.Done() 
    HelloPrint(j) }(i)
} 
    wg.Wait() 
} 
func main() { 
    ManyGoWait() 
}

3.Go Module

查阅资料得知:Go 语言中正式官宣的项目依赖解决方案,Go modules(前身为vgo)于 Go1.11 正式发布,在 Go1.14 已经准备好,并且可以用在生产上了,Go 官方也鼓励所有用户从其他依赖项管理工具迁移到 Go modules。
它解决了一些问题:

  • Go 语言长久以来的依赖管理问题。
  • “淘汰”现有的 GOPATH 的使用模式。
  • 统一社区中的其它的依赖管理工具(提供迁移功能)

4.依赖管理

-   Gopath

-   Go Vendor

-   Go Module

以上的顺序也是依赖管理的发展史!
其实第一个阶段——Gopath:是一个环境变量,其中有三个部分:

  • bin:项目编译的二进制文件
  • pkg:项目编译的中间产物,加速编译
  • src:项目源码,项目代码直接依赖src下的代码go get下载最新版本的包到src目录下 存在的弊端:无法实现package的多版本控制

第二个阶段——Go Vendor:项目目录下增加vender文件,所有依赖包副本形式放在$ProjectRoot/vender
依赖寻找方式是从Go Vender到Gopath(也就是Go Vender中没有的才会去Gopath中找有点像Java的双亲委派机制) 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。 存在的弊端:更新项目的时候可能导致编译错误的冲突;无法控制依赖的版本。
第三个阶段——Go Module:

  • 通过go.mod文件管理依赖包版本
  • 通过go get/go mod指令工具管理依赖包

依赖管理的三要素:

  • 配置文件,描述以来——go.mod
  • 中心仓库管理依赖库——Proxy
  • 本地工具——go get/mod

5.单元测试

-   单元测试概念
概念:对软件中的最小可测试单元进行检查和验证。
-   Mock测试
概念:在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
-   基准测试
概念:指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试