Go语言工程实践 | 青训营笔记

162 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第一篇笔记

Go语言进阶

1.并发和并行

并发:多线程程序在一个核的cpu上运行

并行:多线程程序在多个核的cpu上运行

Goroutine

协程:用户态,轻量级线程,栈MB级别。切换调用由Go语言本身完成,较线程轻量许多。

线程:内核态,线程跑多个协程,栈KB级别。线程的创建,切换,停止都属于很重的系统操作,较消耗资源。

实际开发过程中开启协程:

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

输出结果

![JK8H3QXO86OW]3ZIG(0WM%I.png](p6-juejin.byteimg.com/tos-cn-i-k3…?)

简单来说就是同时跑,先跑完的先输出

Channel

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

有缓冲通道 make(chan int)

无缓冲通道 make(chan int,2)

![)YV{R_`2[%~1(X(9_({E.png

channel的简单使用:

func main() {
	var src chan int
	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 {//消费者1
			dest <- i * i
		}
	}()
	for i := range dest {//消费者2
		println(i)
	}
}

使用channel可使得生产效率高于消费效率,防止因等待消费而产生阻塞。

并发安全

互斥锁:go 语言中保留了通过共享内存实现通信的机制,这种情况会存在多个 goroutine 同时操作同一块内存资源的情况,可能导致并发安全的问题。

这种情况需要通过加锁的方式解决并发安全问题。

Go语言标准库中可以用sync.Mutex实现。

计数器WaitGroup:代替time.Sleep(),保证所有线程运行完,且不会浪费时间。

依赖管理

Go Module

现在普遍用Go Module进行项目管理

一般在创建的项目文件夹下用cmd输入go mod init (项目名)来创建一个go.mod文件,以此进行依赖管理。

依赖分发-Proxy

go.mod中的许多依赖都来自多版本代码仓库管理系统。

Go Proxy是一个服务站点,会缓存源站中的软件内容,使用Go Proxy以后,构建时会直接从站点拉取依赖。

![][G6`(3KUPL4]}FX4TF%6HS.png](p3-juejin.byteimg.com/tos-cn-i-k3…?)

Go Proxy的使用:Go语言通过设置环境变量GOPROXY来设置具体的服务站点。可以通过逗号设置多个Proxy站点,最后如果这几个都没有找到,那么会通过direct进行回源,也就是回到本来的请求站点,而不是代理站。

X48YDCJKAM%5~SQWOGX}8E2.png

go mod:注意go mod init使用时后面加哥项目名,如go mod init haha,项目名为haha,然后在每次引用库时可以直接使用go mod tidy来更新依赖。

![1VSQ5Z]CM}LTHO)DZWXF2EG.png](p6-juejin.byteimg.com/tos-cn-i-k3…?)

测试

测试可以保证运行质量,提升运行效率,避免事故,是十分重要的

N_N4MD77[2]0LJ`2`Q{0U.png

单元测试

测试文件以_test.go结尾,若是goland会自动识别是否为测试文件(vscode未试过)

func TestXxx(*testing.T)

初始化逻辑放入TestMain中

L9PLB)9~ASTS2GC%8(@J1.png

![RQH}$B2]AXHSKJ9JX5R65P.png

Mock测试

如果程序有外部依赖,在不同的测试环境,外部依赖信息可能会发生变化。比如程序需要打开某个文件,如果把相同的程序放在不同的环境测试,该文件的路径可能不一致。这就不符合稳定和幂等两个条件。

通过打桩(Mock)可以解决这个问题。打桩后,就不再依赖本地文件。

利用monkey库可以快速实现打桩:

![XSILEBGE{445YK_PRK1)NW.png

基准测试

基准测试是指测试一段程序的运行性能及耗费 CPU 的程度。而我们在实际项目开发中,经常会遇到代码性能瓶颈,为了定位问题经常要对代码做性能分析,这就用到了基准测试。使用方法类似于单元测试。

基准测试优化:

利用字节跳动开发的fastrand库进行优化,性能可以提升很多倍,在大多数情况都适用。

课后作业

课后作业的话基本上是照着示例代码写,这里主要讲讲怎么测试。

首先肯定是开启server.go

开启后,可以用apifox或者postman去测试,我是用apifox。

如果是用apifox的话,有客户端或者网页端,我是在网页端测试的,在网页端首先打开示例项目,然后新建一个快捷请求。接下来只需要发送GET请求和POST请求就行了。

1654881575759.png

GET请求的话不带参数,然后注意格式,最后一个数字2是topic_id,也就是本地文件data/topic里的,成功的话会返回以下内容,即输出topic里的内容。

go实践1.png

然后是POST请求,主要得带content参数,即评论内容,成功的话会返回以下内容,id是由雪花算法生成的。

go实践2.png

再回到goland看里会看到接受的请求,并且POST请求会将评论内容写入本地的post文件里。

go实践3.png