这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
Go为什么快?
其实这里的快主要是指并发。 Go在并发方面之所以出色,主要是因为自己实现了一套调度器,用户态线程比1:1模型下的用户态线程更清,占用空间更小(kb级别)。
提到并发,自然要提到多routine的通信。golang提倡通信基于共享内存,而非基于共享内存通信。我个人对这句话的理解就是抽象通信的过程,把语义与实现分离(通信与对共享内存区域的操作分离)。
在go中,通信主要是依靠channel。很像消息队列喔。
对于没有缓冲区的通道,会让发送routine和接收routine同步化。因此也叫同步通道。同步通道是线程安全的。 如果不喜欢这种感受,可以用有缓冲通道。这是典型的生产者 消费者模型。
当然,除了routine之间的通信,互斥、同步也是必须的。golang的sync.Lock是很经典的互斥锁。
waitGroup,类似于java里我们join各个线程。或者CountDownLatch。
Go依赖管理
依赖管理要解决的核心问题:因为不同项目依赖的库不同、库的版本也不同。所以依赖管理最重要的就是管理项目所依赖的库的版本。
go src之前已经体验过了,pkg是加速编译用的这个之前完全没体验过。 这套机制不能实现gopath的多版本控制。
go vender其实就是解决gopath的多版本控制问题。他解决了,但又没完全解决··· 现在用的都是go mod了。
可以看到这三个规则几乎和maven一模一样。
单元依赖依靠路径+版本号唯一定位了依赖库。
版本
版本则大概有这两类。
直接/非直接 依赖
direct和indirect是指是否直接依赖。A -> B是直接依赖, A -> C -> D,则对D就是非直接的。
对于没有go.mod文件且项目版本在v2以上的话,会加上incompatible。
依赖图
在这种情况下,如果保证v1.3 v1.4 会选择v1.4。
依赖分发 GOPROXY
依赖分发的时候,会按照我们配置的proxy链一层一层往下找。
Go GET
Go Mod
测试
回归测试:QA同学去手动使用软件。 集成测试:对系统功能做测试,自动化。测试接口之类的。 单元测试:对单独的函数、模块做测试。
Go 单元测试格式
assert
覆盖率
覆盖率主要是谈测试覆盖了多少行源码。会根据传入函数的参数去计算。
依赖
我们的服务可能依赖一些文件、数据库。而测试希望是稳定、幂等的。所以我们会去Mock。
打桩
这里的打桩是指,我们想运行函数A,我们给他打个wrapper。实际运行的就是wrapper了。wrapper要卸载。具体写法就像图片里这样。(用了Monkey库)
这个例子主要展示了如何解耦。Monkey库的实现机制是根据go的运行时去找到我们要执行的原函数的地址,把函数做一下替换,测试完再把原来的函数放回去,即可。用到了Unsafe包。
说真的这是我第一次听实现。很爽。
项目
分层结构
这里用entity表示一个结果实体,用model去对应数据库。
数据层主要是想屏蔽数据来源差异。
之后主要是一些go独有的做法了,比如在service层封装数据流。
总结
今天对我来说,主要收获是对go的并发、包管理、测试、打桩有了基本了解,以及熟悉了go的web项目结构。