Go工程实践|青训营笔记

88 阅读3分钟

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

  • 并发编程
    • 并发与并行
      • 并发:多线程程序在一个核的cpu上运行
      • 并行:多线程程序在多个核的cpu上运行
    • 协程与线程
      • 携程:用户态,轻量级线程,栈KB级别
      • 线程:内核态,线程跑多个协程,栈MB级别
    • 协程间通信:提倡通过通信共享内存而不是通过共享内存实现通信
      • 通道/Channel
        • 创建:make(chan elemType,[buffer size])
          • 无缓冲通道 make(chan int) 使接收方和发送方同步化
          • 有缓冲通道 make(chan int,2) 缓冲区满会阻塞 可以解决生产者和消费者速度不均衡造成的效率问题
      • 并发安全Lock
        • lock sync.Mutex
        • lock.Lock()
        • lock.Unlock()
      • WaitGroup
        • var wg sync.WaitGroup
        • Add(delta int) 计数器+delta
        • Done() 计数器-1
        • Wait() 阻塞直至计数器为0
  • 依赖管理
    • 版本迭代
      • GOPATH
        • 项目代码直接依赖src下代码
        • go get下载最新版本的包到src目录下
          • bin 项目编译的二进制文件
          • pkg 项目编译的中间产物,加速编译
          • src 项目源码
        • 弊端:无法实现package的多版本控制
      • GO Vendor
        • 项目目录下增加vendor文件夹,所有依赖包副本形式放在$ProjectRoot/vendor
        • 依赖寻址方式: vendor => GOPATH
        • 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题
        • 问题:无法控制依赖版本。更新项目有可能出现依赖冲突,导致编译出错
      • Go Module
        • 通过go.mod文件管理依赖包版本
        • 通过go get/go mod指令工具管理依赖包
        • 终极目标:定义版本规则和管理项目依赖关系
    • 依赖管理三要素
      • 配置文件,描述依赖 go.mod
      • 中心仓库管理依赖库 Proxy
      • 本地工具 go get/mod
    • go mod 用法
      • init 初始化,创建go.mod文件
      • download 下载模块到本地缓存
      • tidy 增加需要的依赖,删除不需要的依赖
  • 测试
    • 单元测试
      • 规则
        • 所有测试文件以_test.go结尾
        • func TestXxx(t *testing.T)
        • 初始化逻辑放在TestMain中,在包层面生效
        func TestMain(m *testing.M){
            // 测试前:数据装载、配置初始化等前置工作
            
            code := m.Run()
            // 测试后:释放资源等收尾工作
            
            os.Exit(code)
        }
        
    • Mock测试
      func TestProcessFirstLineWithMock(t *testing.T){
          monkey.Patch(ReadFirstLine, func() string{  //打桩
              return "line110"
          })
          defer monkey.Unpatch(ReadFirstLine) //卸桩
          line := ProcessFirstLine()
          assert.Equal(t,"line000",line)
      }
      
    • 基准测试 即压力测试
  • 项目实践
    • 分层结构
      • 数据层Repository:数据Model,外部数据的增删改查
      • 逻辑层Service:业务Entity,处理核心业务逻辑输出
      • 视图层Controller:视图View,处理和外部的交互逻辑
    • 单例模式
      • sync.Once 多并发场景只执行一次,减少资源浪费
      var topicOnce sync.Once
      topicOnce.Do(
          func(){
              topicDao = &TopicDao{}
          }
      )
      
    • service层:参数校验->准备数据->组装实体
    • Router: 使用gin搭建框架
      • 初始化数据索引
      • 初始化引擎配置
      • 构建路由
      • 启动服务
  • homework
    • 支持发布帖子
    • 本地ID生成需要保证不重复、唯一性
    • Append文件,更新索引,注意Map的并发安全问题