这是我参与「第五届青训营 」笔记创作活动的第1天
1.16 Go语言进阶 - 工程进阶|青训营笔记
概述:课程主要分为以下几个部分
1.并发编程
Go可以充分发挥多核优势,高效运行程序
-
协程Goroutine
Go一次可以创建上万个协程,这也是Go擅长高并发的原因所在
Go语言开启一个协程是很方便的,只需要在语句前面加上Go关键字
例如:
func hello(i int) { println("hello world : " + fmt.Sprint(i)) } func main() { for i := 1; i < 5; i += 1 { go func(j int) {//通过go关键字实现,创建协程 hello(j) }(i) } time.Sleep(time.Second) } 输出结果是乱序的,所以输出是并行打印的
-
通道Channel
通道(channel)是用来传递数据的一个数据结构。
go提倡通过通信来共享内存,而不是通过共享内存来通信,而通信是通过通道来实现
具体操作:
make(chan 元素类型,[缓冲大小]) 无缓冲通道 make(chan int) (同步通道) 有缓冲通道 make(chan int,2) //通道具体例子 //A子协程发送数字 //B子协程计算数字的平方 //主协程输出最后的平方数 func Cal() { src := make(chan int) //无缓冲通道 dest := make(chan int, 3) //有缓冲通道 go func() { //协程A defer close(src) //用于延迟关闭通道src for i := 0; i < 10; i += 1 { src <- i//操作符 <- 用于指定通道的方向,发送或接收,把i发送到src通道 } }() go func() { defer close(dest) for i := range src { dest <- i * i } }() for i := range dest { println(i) } } -
锁Lock
在并发时,对于临界区资源的访问,如果不加锁,有时候会出现并发安全问题
var ( x int64 lock sync.Mutex //互斥锁,开箱即用的类型 ) func addLock() { for i := 0; i < 2000; i++ { lock.Lock() //加锁 x += 1 lock.Unlock() } } func addunLock() { for i := 0; i < 2000; i++ { x += 1 } } func Add() { x = 0 for i := 0; i < 5; i++ { go addLock() //开启5个携程,来对全局变量执行加法操作 } time.Sleep(time.Second) println("x=", x) x = 0 for i := 0; i < 5; i++ { go addunLock() } time.Sleep(time.Second) println("x=", x) }第一次是加锁的,第二次是不加锁的
-
线程同步WaitGroup
Add Done Wait 计数器:开启协程+1,执行结束-1,主协程阻塞直到计数器为0
2.依赖管理
指各种开发包
-
Gopath
-
Go Vendor
-
Go Module(广泛应用)
通过go.mod文件管理依赖包版本
通过go get/go mod指令工具管理依赖包
2.1 Go.mod文件详解
主要有三部分
1.依赖管理基本单元
2.原生库
3.单元依赖
依赖标识: [module path] [Version / Pseudo-version]
此处的version有两种类型
1.语义化版本
2.基于commit伪版本
2.2 依赖分发-Proxy
2.3 本地工具 Go get/mod
3.单元测试
测试规则
所有测试文件以_test.go结尾
3.1.4 单元测试——assert
是一个github上的用于帮助我们测试的一个包
3.5.3 基准测试-优化
随机数生成函数
rand.Intn(n):生成一个小于n的随机数
//传统随机函数
fastrand.Intn(n)
//快速生成一个随机数,效率更高,推荐使用
4.项目实战
4.1需求描述
1.展示话题(标题、文字描述)和回帖列表
2.暂时不考虑前端页面实现,仅仅实现一个本地web服务
3.话题和回帖数据用文件存储
4.3 ER图(话题和帖子的结构体)
话题——帖子(一对多)
4.4 分层结构
数据层 数据Model,外部数据的增删改查,对service层透明
逻辑层 业务Entity,处理核心业务逻辑输出
视图层 视图view,外部和外部的交互逻辑
4.5 组件工具
1.Gin高性能 go Web 框架
2.Go Mod
4.6 Resposity
实现两个查询操作
1.实现对应话题查询(id)
2.查询到话题对应的回复帖子
可以用索引去定位数据(map)
初始化话题内存索引,先将文件内容读出来
ps
此处用到了一个sync.Once的关键字
var (
topicDao *TopicDao
topicOnce sync.Once
//关键字
//适合在高并发场景下只执行一次的场景,也就是单例模式,减少了存储的浪费
)
sync.Once 是 Go 语言实现的一种对象,用来保证某种行为只会被执行一次
利用topicOnce.Do()来实现,如图
同样的,可以用类似的方法来实现查询帖子
4.7 Service
定义两个实体
service层流程:
参数校验->准备数据->组装实体
获取topic和获取回帖信息,这两个操作是没有依赖关系的,所以可以并行去做,开两个协程,提高效率
4.8 Controller
4.9 Router
初始化数据索引
初始化引擎配置
构建路由
启动服务
参考