Golang部分实践 | 青训笔记

142 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记

个人随笔,写的可能比较杂。

工程实践

  1. Goroutine 协程 提倡通过通信共享内存(而不是通过共享内存实现通信) image.png

2.channel 通道 (通过通信共享内存)分为有缓冲通道和无缓冲通道

    make (chan 元素类型,[缓冲大小]) 
    无缓冲 make(chan int) 
    有缓冲 make(chan int, 2) (缓冲满了装不下,阻塞发送 -> 生产消费模型)
    defer  用做延迟资源关闭

在Go语言中,通道是goroutine与另一个goroutine通信的媒介,并且这种通信是无锁的。换句话说,通道是一种允许一个goroutine将数据发送到另一个goroutine的技术

image.png

image.png

通过两个管道实现两个线程输出数据:

image.png

合并管道:

image.png

chan string这样的写法能够使用读写功能双向管道外,还可以创建出单向管道,如<-chan string只能从管道中读取数据,而chan<- string只能够向管道中写入数据。

单行<-XX 写法的意思

image.png

依次到并发的实例:

image.png

image.png

3.mutex 锁 (通过共享内存实现通信)

      定义: var lock sync.Mutex 当需要对共享内存里进行修改 
      先 lock.Lock() 
      .. 
      用完了 lock.Unlock()

4. WaitGroup 实现并发任务同步 (前面都用time.Sleep(time.Second) 实现暴力阻塞) sleep 也是为了防止主线程比子线程提前结束 也是在sync包下

    Add(delta int)  计数器 +delta
    Done() 计数器-1 
    Wait() 阻塞知道计数器为0 
    
    定义 : var wg sync.waitGroup wq.Add(delta: 5) // 因为要开五个携程 
    for i := 0; i < 5; i ++{ go func(j int) {
        defer wg.Done() // 子协程任务结束, 计数器-1 
        hello(j) //自定义函数输出 
        }(i) 
    } 
    wg.Wait() // 进行阻塞 
    
    输出:4 0 1 2 3

依赖管理

(依赖:各种开发包,利用他人工具提高开发效率)

go的依赖管理的三个阶段 : GOPATH -> GO Vendor -> GO module

  1. GOPATH 环境变量$GOPATH

    项目代码直接依赖src下的代码 (go get 下载最新版本的包到src 目录下) 弊端无法实现package多版本控制

  2. Go Vendor

    项目目录下增加vendor 文件夹 项目依赖 (先找)govendor = > (再去)gopath 问题 无法控制依赖版本,因为都是依赖项目源码

  3. Go Module 解决了问题

    通过 go.mod 文件管理依赖包版本 通过 go get/go mod 指令工具管理依赖包 最终可以:定义版本规则和管理项目依赖关系

依赖管理三要素

1.配置文件 , 描述依赖了那些包,唯一去定位 go.mod
2. 中心仓库管理依赖库 (go.mod里) proxy 
3. 本地工具 go.get / mod 

(1). 依赖配置go.mod 托管到github上

    require{ 
        [Module Path][Version/Pseudo-version] 
    }

(2).依赖配置

    语义化版本 如v1.2.3 (${MAJOR}.${MINOR}.${PATH})
    基于commit 伪版本 v1.2.0-yyyymmddhhmmss-abchdefh1234 (同上版本-时间戳-hash校验码)

go.mod上一些关键词的解析:

(3). indirect

写法: 对于没有直接导入的依赖模块后标识“ //indirect” (正常是A->B 直接依赖 A->B->C a对c间接依赖)

(4).incompatible

写法: 对于之前仓库直接已经2+,没有go.mod文件且主版本2+的依赖会在后边写“+incompatible”

依赖分发

(5). 依赖分发-回源 直接关联去GIthub , SVN

(6).依赖分发-Proxy 稳定可靠 (当作者删除某个版本,仍然稳定) 在Develop 和 GItHub之间加一层Proxy

(7).依赖分发-变量GOPROXY

go.mod工具

(1)go.get example.org/pkg

    @updata 默认 
    @ none 删除依赖 
    @v1.1.2 拉去特定版本 
    @23ddf 拉取特定commit 
    @master (指定分支)拉取分支最新commit 

(2).go mod

     init 初始化 创建go.mod 文件(项目开始步骤) 
     download 下载模块到本地(把所有依赖拉下来) 
     tidy 增加需要依赖删除不需要的(每次执行前可以运行一次,删一下) 

测试

(用于避免事故的最后屏障)

  1. 回归测试

  2. 集成测试 对系统功能维度,对服务暴露的某个接口

  3. 单元测试 面对测试开发阶段,对单独函数模块做功能验证 (覆盖率最大,决定代码质量)

image.png 规则:

     文件 都是xxx_test.go 
     测试函数 func TestXxx(XX *testing.T) 
     初始化逻辑放到 func TestMain(m *testing.M)

image.png

测试指令: go test [flag][packages]

开源的测试包

如 assert

image.png

image.png

image.png

参考: 《 Golang 并发编程实战——协程、管道、select用法》