Go语言工程实践(四) | 青训营笔记

117 阅读2分钟

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

第二节课-GO工程实践

  1. 语言进阶

    并发编程角度​

    并发VS并行

    • 并发:多线程程序在一个核的cpu上运行
    • 并行:多线程程序在多个核的cpu上运行

    ==GO可以充分发挥多核优势,高效运行。==

    1. Goroutine

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

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

      • 用法:

        go func(j int){
        //your code
        }(j)
        
    2. CSP(Communicating Sequential Processes)

      提倡通过==通信共享内存==而不是通过共享内存而实现通信。

    3. Channel

      make(chan 元素类型,[缓存大小])

      • 无缓冲通道 make(chan int)
      • 有缓存通道 make(chan int,size)
      • 发送ch<-i
      • 接收i<-ch
    4. 并发安全Lock

      • 声明var mutex sync.Mutex
      • 加锁mutex.Lock()
      • 解锁mutex.Unlock()
    5. WaitGroup

      • 声明var waitGroup sync.WaitGroup

      • 计数器+delta waitGroup.Add(delta)

      • 计数器-1 waitGroup.Done()

      • 阻塞直到计数器为0 waitGroup.Wait()

      • 使用例子:

        1. 开启协程+1
        2. 执行结束-1
        3. 主协程阻塞直到计数器为0.
    6. 小结

      主要通过GoroutineChannelSync实现

  2. 依赖管理

    1. 依赖管理演进

      GOPATH=>Go Vendor=>Go Module

    2. GOPATH

      • 目录包含bin,pkg,src三个子目录
      • 项目代码直接依赖src下的代码
      • go get下载最新版本的包到src目录下
      • 问题:在A和B两个不同项目依赖于某个package的不同版本时无法实现package的多版本控制
    3. Go Vendor

      • 项目目录增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
      • 依赖寻址方式:vendor =>GOPATH
      • 解决了GOPATH中的冲突问题
      • 问题:项目A依赖Package B和Package C时,若B和C依赖于Package D的不同版本D-v1, D-v2时则无法解决冲突
      • 问题原因:仍然是依赖于包的源码而不能标识依赖的不同版本
    4. Go Module

      1. 特点

        • 通过go.mod文件管理依赖包版本
        • 通过go get/go mod指令工具管理依赖包
        • 目标:定义版本规则和管理项目依赖关系
      2. 依赖管理三要素

        • 配置文件,描述依赖 go.mod
        • 中心仓库管理依赖库 Proxy
        • 本地工具go get/mod
        • 依赖标识:[Module Path][Version/Pseudo-version]
      3. version

        • 语义化版本

          MAJOR.{MAJOR}.{MINOR}.​${PATCH}

          • v1.3.0
          • v2.3.0
        • 基于commit伪版本

          vX.0.0-yyyymmddhhmmss-abcdefgh1234

          • v0.0.0-20220401081311-c38fb59326b7
          • ...

        ==依赖包版本选择最低的兼容版本==

    5. 依赖分发

      1. 回源

        • 无法保证构建稳定性
        • 无法保证依赖可用性
        • 增加第三方压力
      2. Proxy

        • 稳定,可靠
      3. 变量GOPROXY

        GOPROXY=”proxy1.cn,https://proxy2.cn,…"

        服务站点URL列表,“direct"标识源站

        ==proxy1=>proxy2=>direct==

    6. 工具

      1. go get

        • go get example.org/pkg
        • @update 默认
        • @none 删除依赖
        • @v1.1.2 tag版本,语义版本
        • @23dfdd5特定的commit
        • @master分支的最新commit
      2. go mod

        • init 初始化,创建go.mod文件
        • download下载模块到本地缓存
        • tidy增加需要的依赖,删除不需要的依赖
  3. 测试

    1. 单元测试

      • 测试输出与期望输出校对

      • 规则

        • 所有测试文件以_test.go结尾
        • func TestXxx(t *testing.T){//your code}
        • 初始化逻辑放到TestMain()
      • 运行go test [flags][packages]

      • assert

      • 测试Tips

        • 覆盖率需50%~60%,热点代码需80%
        • 测试分支相互独立、全面覆盖
        • 测试单元力度足够小,函数单一职责
    2. Mock测试

      外部依赖=>稳定&幂等

      • monkey

      • 快速Mock函数

        • 为一个函数打桩
        • 为一个方法打桩
    3. 基准测试

      • 优化代码,需要对当前代码分析
      • 内置的测试框架提供了基准测试的能力
      • func BenchXxx(b *testing.B){//your code}
      • b.ResetTimer()b.RunParallel(func(pb *testing.PB){//your code})
  4. 项目实战

    1. 需求分析

    2. 需求用例

    3. ER图

    4. MVC分层结构

    5. web框架:Gin

      1. 初始化数据
      2. 初始化引擎配置
      3. 构建路由
      4. 启动服务