深入了解Go项目 | 青训营笔记

133 阅读4分钟

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

今天我学习了Go基础课的三四节,在时长合计共约90分钟的视频中,我收获到Go语言在实战项目中所具有的亮眼的优势,并且初步接触了Go项目的一些操作上的实际经验。

一、本堂课重点内容:

  • 本堂课的知识要点有哪些?
    第三节课当中我认为比较重要的,在Go语言的高并发编程中,Goroutines可以说是它的最佳特性。它是一种轻量级的计算线程,与操作系统截然不同—— 它具有着异步编程的可伸缩性优势,也就是说它可以充分发挥多核优势、高效运行。
    此后还介绍了Go的一项工程实用知识:依赖管理,也就是使用Go Module方案来管理依赖,以此来达到定义版本规则和管理依赖关系的目的,后面还讲了依赖管理的三要素。
    第四节课讲了测试的重要性,以及单元测试的一些做法:用Assert测试、用Mock测试,最后还介绍了一下基准测试。后面又用一个生动形象的示例项目讲解了一下。

二、详细知识点介绍:

  • 本堂课介绍了哪些知识点?
    第三节课教会了我Go的并发编程和依赖管理
  1. Go 实现“快速”打印(多线程并行打印),如课件中所举的例子:
func prtf(i int){
    println("outgo : " + fmt.Sprint(i))
}

func OutGo(){
    for a:=0;a<6;a++ {
        go func(x int){
            prtf(x)
        }(a)
    }
    time.Sleep(time.Second)  //保证子线程执行完之前,主线程不退出
}

在以上情况下,可以快速打印

outgo : 4
outgo : 1
outgo : 0
outgo : 5
outgo : 2
outgo : 3
  1. Channel建立缓冲通道式的协程,举个例子:
func RunCal(){
    src := make(chan int)
    dst := make(chan int, 3)
    go func(){
        defer close(src)
        for i:=5;i<9;i++ {
            src <- i
        }
    }()
    go func(){
        defer close(dst)
        for i := range src {
            dst <- i*i
        }
    }()
    for i := range dst {
        //复杂操作
        println(i)
    }
}

在以上情况下,可以复杂地快速打印(5、6、7、8的平方)

outgo : 25
outgo : 36
outgo : 49
outgo : 64

3.并发安全Lock
用于处理或修改线程冲突问题,例如1中所提到的:保证子线程执行完之前,主线程不退出。当时这里采取的方法也是比较简单粗暴的,而现在可以用Lock进行,这部分课件也已经阐述得较为详细,就不再赘述了。
4.依赖管理的演进,从GOPATH到Go Vendor到Go Module,也就是目前主流是在使用Go Module方案来管理依赖,以此来达到定义版本规则和管理依赖关系的目的。

第四节课提出了三个层面的测试及其方法(单元测试、Mock测试、基准测试)
1.assert函数可以快速验证方法的结果 2.Mock函数可以快速打桩 3.基准测试可以用于代码调优时,用于分析代码
(以上部分具体的实现在课程中也都有所提及,代码部分也可以详看课件对应的内容)
后面还提到了一个实际的项目作为综合的运用。

三、实践练习例子:

  • 有什么实践举例帮助理解知识点?
    这里需要感谢掘金团队学习课件中提供的Gin高性能Go Web框架,极大的方便了我对于示例项目的学习理解,如果有后来人也可以就此拉取Git项目:github.com/gin-gonic/g…

四、课后个人总结:

  • 本章有什么知识点不容易掌握?
    可能多线程这些概念对于我而言较为生僻,虽然在操作系统当中有所学习,但是与具体开发还是大不相同的,所以算是一个困难点(如线程锁)。
  • 什么地方容易与其他内容混淆?
    感觉Go Routine与操作系统的线程容易相混淆,主要区别如下:
    1.内存占用方面,Go Routine内存占用为KB级别,thread内存占用为MB级别
    2.创建销毁消耗方面,Go Routine是用户级的,消耗非常小,是由Go Routine自己管理的,thread是内核级的,消耗巨大,一般要用线程池
    3.切换成本,Go Routine只需保存3个寄存器:PC,SP,BP。而thread切换需要保存各种寄存器——16 general purpose registers, PC (Program Counter), SP (Stack Pointer), segment registers, 16 XMM registers, FP coprocessor state, 16 AVX registers, all MSRs etc
    也因此,go routine切换时间200ns,threads切换时间1000-1500ns,显然go routine切换成本比thread也要小得多。

五、引用参考:

  • 我参考了哪些外部博客/笔记/文章?
    我参考了掘金内部课中的Go基础课程,也就是此次掘金内部课程:
    juejin.cn/course/byte… 另外还参考了Foxtail-Grass Studio的专辑封面,作为此次笔记的封面
    关于区分go routine和thread的部分,参考了CSDN博客的片段:blog.csdn.net/Haikuotiank…
  • 文章中有什么地方是我参考引用了外部博客/笔记/文章的?
    主要是课程的主要知识点总结,采用了一边阅读课件一边记录的方式进行了个人的一些学习总结。