一.go语言为什么这么快:协程、并发
-
go可以充分发挥多核优势,高效运行,那么实现高并发主要原因就是协程。协程比线程轻量。
- 线程:属于内核资源,它的变化、操作都是有操作系统控制,而且需要很大的资源,
- 协程:属于轻量级的线程,它的调度由go语言本身完成,线程上可以跑多个协程
-
go语言开启一个协程的方法:go+一个函数,相当方便。
- 例如 go func1()
-
go语言提倡通过通信共享内存,而不是通过共享内存而实现通信。为什么呢?因为通过共享内存通信的话,就避免不了加锁了,对共享的内存进行加锁,这样就影响了go程序的性能。
-
go中协程之间是通过Channel进行通信,Channel是一个队列,遵循先进先出的原则。、
-
Channel创建:make(chan type,[缓存大小])
-
Channel分类:通过是否有缓存大小分为无缓冲通道make(chan int)、有缓冲通道(chan int,2)
-
区别:使用无缓冲通道**会使发送的gorountine和接收的gorountine同步化,**因此无缓冲通道也被称为同步通道。
func main() { src := make(chan int) dest := make(chan int, 3) go func() { defer close(src) for i := 0; i < 10; i++ { src <- i; } }() go func() { defer close(dest) for i := range src { dest <- i * i } }() go func() { for i := range dest { println(i) } }() }
-
-
-
waitGroup的作用:
-
当我们开启一个协程后,主线程也还在执行中,那么如果主线程先结束了,协程还没有结束,此时协程也退出,这样导致结果肯定错误。
-
有什么办法可以解决这个问题呢?
-
第一个:不优雅的解决方案,就是在主线程中sleep一段时间,打赌协程在这段时间内就会结束,那么主线程可以等到协程结束后再结束。
-
就是使用waitGroup:有三个函数
- Add(deleta int),每增加一个协程计数器加一
- Done(),每结束一个协程计数器减一
- Wait(),阻塞等待计数器为0
例子:
func hello(j int){fmt.Println(j)}func main(){var wg sync.WaitGroupwg.Add(5)for i :=0;i<5;i++{
go func(j int){
defer wg.Done()
hello(j)
}(i)}wg.Wait()}
-
-
二.依赖管理
- go的依赖管理经历了三个过程:GOPATH->GO Vendor->Go Module
- GOPATH:是go语言的环境变量,是go项目的工作区,下面有三个包bin、pkg、src,分别存放的文件是项目编译的二进制文件、项目编译的中间产物,加速编译、项目源码。
- 项目代码直接依赖src下的代码,go get下载最新版本的包到src目录下
- GOPATH弊端:无法实现package的多版本控制
- Go Vendor:项目目录下增加vendor文件,所有依赖包副本形式放在ProjectRoot/vendor。此时寻找依赖的方式是先在verdor下找,如果没有就去GOPATH下找,解决了多个项目需要同一个package依赖冲突问题
- go vendor问题:无法控制依赖的版本、更新项目又可能出现依赖冲突,导致编译错误
- Go Module:通过go.mod文件管理依赖版本版本,通过go get/go mod指令工具管理依赖包。
- 依赖管理三要素:
- go.mod配置文件,描述依赖
- Proxy中心仓库管理依赖库
- go get/mod本地工具
- 依赖管理三要素:
- GOPATH:是go语言的环境变量,是go项目的工作区,下面有三个包bin、pkg、src,分别存放的文件是项目编译的二进制文件、项目编译的中间产物,加速编译、项目源码。
三.测试
- 测试是避免事故发生的一到屏障。
- 测试分类:回归测试、集成测试、单元测试。成本依次减低,作用越来越大
- 单元测试-规则:
- 所有测试文件以_test.g结尾
- 测试函数:func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
- 单元测试-覆盖率:就是代码执行的行数,和简单。 一般覆盖率是50-60%
- 单元测试-规则:
四.项目
- 项目内容:展示话题和回帖列表
- er图:一个topic话题结构体、post回帖结构体
- 封层结构:三个部分数据层、逻辑层、视图层。
- 数据层:底层数据model,用于封装外部数据的增删改查,主要面向service层,并且对service层透明。
- 逻辑层:通过数据层返回数据进行打包封装层成entity
- 视图层:处理和外部交互逻辑和数据,比如json化数据。