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

47 阅读2分钟

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

day2

  • 语言进阶(从并发编程视角,了解go适合高并发场景的本质)
  • 依赖管理
  • 单元测试,上线的最后一环
  • 项目实战

  1. 并发编程

3.1 协程

并发、并行

协程:用户态,轻量级线程,栈MB级别。

线程:内核态,线程跑多个协程,栈KB级别。

内存中heap和stack的区别?

操作系统中堆和栈的区别?

开启协程

在函数的前面加go关键字

协程之间的通信,怎么做到?通过通信来共享内存

3.2 通信共享内存

CSP (Communicating Sequential Processes)

Goroutine: go程序并发的执行体

通道:连接协程,类似传输队列

3.3 通道的具体操作

func CalSquare() {
    src := make(chan int)//创建一个channel,生产者
    dest := make(chan int, 3) //创建一个channel,消费者
    go func() {
        defer close(src)
        for i := 0; i < 10; i++ {
            src <- i
        }
        close(src)
    }()
    go func() {
        defer close(dest)
        for i := range src {
            dest <- i * i
        }
    }()
    for i := range dest {
        //复杂操作
        println(i)
    }
}

3.4 并发安全问题:比较难定位。避免对共享内存做些非并发安全的读写操作

代码:加锁和不加锁

package main

import (
   "sync"
   "time"
)

var (
   x    int64
   lock sync.Mutex //互斥锁
)

// 加锁
func addWithLock() {
   for i := 0; i < 2000; i++ {
      lock.Lock()
      x = x + 1
      lock.Unlock()
   }
}

// 不加锁
func addWithoutLock() {
   for i := 0; i < 2000; i++ {
      x = x + 1
   }
}

func Add() {
   x = 0
   for i := 0; i < 5; i++ {
      go addWithoutLock()
   }
   time.Sleep(time.Second) //等待一秒钟
   println("WithoutLock:", x)
   x = 0
   time.Sleep(time.Second) //等待一秒钟
   println("WithLock:", x)
}
func main() {
   Add()
}

3.5 WaitGroup

小结

go并发编程有3种

这里简单做个小结,整个章节主要涉及3个方面,一个是协程,通过高效的调度模型实现高并发操作,一个是通道channel,通过通信实现共享内存,最后sync相关关键字,实现并发安全操作和协程间的同步。

  1. 依赖管理

4.1 go依赖管理的演进:

4.2 依赖管理三要素 (类似Maven)

1.配置文件,描述依赖:go.mod

2.中心仓库管理依赖库 Proxy

3.本地工具 go get/mod

4.3 依赖配置