Go语言进阶与依赖管理|青训营笔记

9 阅读2分钟

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

1.Go语言的并发与并行

  • 多线程程序在一个核的CPU上运行,如下图:

image.png

  • 多线程程序在多个核的CPU上运行

image.png Go语言可以充分发挥多核优势,高效运行。Go语言实现计算机调度模型,完成高并发能力。

**1.1 Goroutine

Go语言的协程开启只需要在函数面前加关键字go,源代码如下:

package main

import (
	"fmt"
	"time"
)

func hello(i int) {
	fmt.Println("hello gorouine: " + fmt.Sprint(i))
}

func HelloGoRoutine() {
	for i := 0; i < 5; i++ {
		go func(j int) { //go语言创建协程:在函数前加go关键字
			hello(j)
		}(i)
	}
	time.Sleep(time.Second)
}

func main() {
	HelloGoRoutine()
}

最终效果如下:

image.png **1.2 Channel

go语言通过通信而共享内存,而不是通过共享内存实现通信。

image.png

使用make(chan元素类型,[缓冲大小]),例如有缓冲通道make(chan int),无缓冲通道make(chan int,2)

image.png

源代码如下:

func CalSquare() {
	src := make(chan int)
	dest := make(chan int, 3) //有缓冲的通道

	//子协程A生成数字
	go func() {
		defer close(src) //defer关闭通道
		for i := 0; i < 10; i++ {
			src <- i
		}
	}()

	//子协程B计算平方
	go func() {
		defer close(dest)
		for i := range src {
			dest <- i * i
		}
	}()

	//主协程打印结果
	for i := range dest {
		println(i)
	}
}

实验结果:

image.png

**1.3并发安全-lock函数保证数据安全

image.png

**1.4 Sync-WaitGroup

*Sleep做延迟

*WaitGroup计数器也可以做延迟:开启协程Add()+1;执行结束Done()方法-1;主协程阻塞直到计数器为0.

image.png

image.png

2.依赖管理

**2.1Go依赖管理演进

GOPATH(无法实现包的多版本控制) -> GO Vendor(可能出现依赖冲突) -> Go Module

Go Module 通过go.mod文件管理依赖包版本;通过go get/go mod指令工具管理依赖包。终极目标是定义版本规则和管理项目依赖关系。

依赖管理三要素包括:go.mod配置文件,描述依赖;Proxy中心仓库管理依赖库;go get/go mod本地工具

**2.2 GoModule依赖管理方案

go module的依赖分发(即从哪里下载)。github是比较常见的代码托管平台,而Go module系统中定义的依赖,最终可以对应到多版本代码管理系统中某一项目的特定提交版本,因此,go.mod对应的依赖可以直接从对应仓库指定软件下载,从而依赖分发。

直接使用版本管理仓库下载依赖,存在多个问题:首先无法保证构建确定性:软件作者可以直接代码平台增加/修改/删除软件版本,导致下次构建使用另外版本的依赖,或者找不到依赖版本;无法保证依赖可用性:依赖软件作者可以直接代码平台删除软件,导致依赖不可用;大幅增加第三方代码托管平台压力。

因此Go Proxy是一个服务站点,可以缓存软件内容,且在源站软件删除后依然可用。

image.pngimage.png

**2.2 GoModule依赖分发-变量GOPROXY

GOPROXY=“proxy1.cn,https://prioxy2.cn…" 服务站点URL列表,优先从Proxy1下载,若不存在,则Proxy2,若还不存在,则直接从源站直接下载(direct控制的)

image.png image.png