Go进阶/依赖管理 | 青训营笔记

91 阅读1分钟

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

前言

复习Go语言的进阶和依赖管理,为开发大项目做好准备

语言进阶

1.高并发

Go语言的高并发性质会导致输出和想象的不一致,需要进行进一步优化,举个例子:

package main

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)
}
func main() {
    HelloGoRoutine()
}

2.并发安全

类似于操作系统中生产者消费者的模型的Go语言版,如果不对变量添加Lock,最终结果和预期会有很大区别。

var (
    x int 64
    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 addWithLock()
     }
     time.Sleep(time.Second)
     println("WithoutLock", x)
     x = 0;
     for i:= 0; i < 5; i++ {
         go addWithLock()
     }
     time.Sleep(time.Second)
     println("WithLock:", x)
 }
 

上述代码没有加Lock结果是一个随机数(反正不等于10000就对了)
只有添加Lock结果才为10000

依赖管理的三种模式

GOPATH模式

$GOPATH:项目根路径 本质上为Go语言支持的一个环境变量,包含 bin,pkg,src三部分

特点:

  • 项目代码直接依赖src下的代码
  • go get 下载最新版本的包到src目录下
    缺点 : 无法支持package的多版本控制

Go Vendor

通过本地化构建的方式在每个项目下都创建一个vendor目录,每个项目所需要的以来都会下载到自己的vendor目录下。在使用包时,会先从当前项目下的vendor目录查找,然后再从GOPATH中查找。
所依赖包副本形式放在 $ProjectRoot/vendor
寻址方式; vendor => GOPATH
优点 : 解决了多个项目需要同一个package的冲突问题。
缺点 :

  • 无法控制依赖的版本
  • 更新项目可以出现依赖冲突,导致编译出错

Go Module

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

依赖管理三要素

  1. 配置文件,描述依赖 go.mod
  2. 中心仓库管理依赖库 Proxy
  3. 本地工具 go get/mod

go.mod配置

module example.com/foobar
go 1.16
require (
    example.com/apple v0.1.2
    example.com/banana v1.2.3
    example.com/banana/v2 v2.3.4
    example.com/pineapple v0.0.0-20190924185754-1b0db40df49a
)
exclude example.com/banana v1.2.4
replace example.com/apple v0.1.2 => example.com/rda v0.1.0 
replace example.com/banana => example.com/hugebanana  

结束语

青训营的课程干货很多,刚学完没过几天就快忘光了,还需要定时的去复习并且复现代码,这样记忆才会更加深刻。