【Go语言入门-工程实践 | 青训营笔记】

53 阅读4分钟

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

主要记录课程的重点和课上所讲项目的每一步以及我的思考

1.语言进阶

Go可以充分发挥多核优势,高效运行,为高并发而生。

1.1并发

首先我们要了解一下相关概念。

并发是指在一个时间段内有多个进程在执行。它的特点是速度更快,可以更快的执行且设计可管理。

与之相对应的,还有并行,并行指的是在同一时刻有多个进程在同时执行。

如果是在只有一个CPU的情况下,是无法实现并行的,因为同一时刻只能有一个进程被调度执行,如果此时同时要执行其他进程则必须上下文切换,这种只能称之为并发,而如果是多个CPU的情况下,就可以同时调度多个进程,这种就可以称之为并行。

1.2协程

协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。

以课程中的快速打印的程序为例

     
     for i := 0; i < 5; i++ {
         go func(j int){
            hello(j)
         }(i)
     }
     time.Sleep(time.Second)
     }

Go语言中开启协程,只需要在开启函数时,,在函数前加go就行。

1.3CSP

协程之间的通信,提倡通过通信共享内存而不是通过共享内存而实现通信

1.4Chanel

Chanel是一种引用类型,创建要通过make关键字。通常是

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

根据缓冲大小,别为无缓冲通道(同步通道)和有缓冲通道

1.4并发安全Lock

在分布式系统中,难免涉及到对同一数据的并发操作,如何保证分布式系统中数据的并发安全呢?分布式锁是一个好的选择。

在这举一个银行取钱的案例

金钱总数:1000¥

取钱人员A,准备从中取走600,这时银行代码要 if 总数>所取金额。在判断的过程中B也要去取钱,B也取了600,这时A那边刚判断完,要取钱了发现出现-200¥,取钱机器崩溃。

Lock锁的出现就是让一个线程可以完整的执行,不会出现多线程访问同一资源的出现数据混乱。其操作方式就是一个线程去抢锁,抢到锁了去执行,没有抢到锁的无法执行,只有等待持有锁的线程释放才能抢锁执行。

1.5WaitGroup

WaitGroup 类实现的功能是:等待一系列协程并发地执行完毕。如果不等待所有协程执行完毕,可能会导致一些线程安全问题。

2.依赖管理

这里的依赖指开发包,我们可以利用他人开发好的工具,提高自己的效率

2.1Go依赖管理演进

GOPATH → Go Vendor → Go Module

2.1.1GOPATH的弊端

当A和B依赖于某一package的不同版本时,无法实现package的多版本控制。

2.1.2Go Vendor

通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。

但它的问题是1.无法控制依赖的版本2.更新项目又可能出现依赖冲突,导致编译出错。

2.1.3Go Module

通过go.mod文件管理依赖包版本,同时通过go get/go mod指令工具管理依赖包。

2.2依赖管理三要素

(1)配置文件,描述依赖 → go.mod

(2)中心仓库管理依赖库 → Proxy

(3)本地工具 → go get/mod

3.测试

测试是避免事故的最后一道屏障。测试分为回归测试,单元测试,集成测试。

单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。

回归测试就是指的是重新运行以前的测试(功能性和非功能性),以确保先前开发和测试的软件在修改后仍能够正常运行。

集成测试是将各个单元组合并进行测试,以验证它们在集成时是否按预期工作。这里的主要目的是测试模块之间的接口。

3.1单元测试

单元测试属于最严格的软件测试手段,是最接近代码底层实现的验证手段,可以在软件开发的早期以最小的成本保证局部代码的质量。

单元测试都是以自动化的方式执行,所以在大量回归测试的场景下更能带来高收益。

单元测试的实施过程还可以帮助开发工程师改善代码的设计与实现,并能在单元测试代码里提供函数的使用示例,因为单元测试的具体表现形式就是对函数以各种不同输入参数组合进行调用,这些调用方法构成了函数的使用说明。

这里列举出课程的单元测试的例子。

func HelloTom() string {
       return "Jerry"
   }
   

func TestHelloTom(t *testing.T) {
     output := HelloTom()
     expectOutput := "Tom"
     if output != expectOutput {
         t.Errorf("Expected %s do not match actual %s",expectOutput, output)
         }
}

单元测试运行的结果是不通过,因为期望是输出Tom,但是实际输出是Jerry。

4.项目实战

这一段是内容是使用go web框架Gin配合MVC模式,开发一个论坛页面的后端,具备一些简单的功能。

5.课后总结

感觉自己的基础还是太薄弱,不少内容一知半解要去找资料,补充了解。要不断充实自己。

6.引用

该文章部分内容来自于以下课程

  • 字节内部课:Go语言入门-工程实践