Go进阶及依赖管理 | 青训营笔记

64 阅读3分钟

Go进阶知识

今天是青训营的第二天,学习了Go的并发相关的特性以及工程的测试等内容,下面是记录

Goroutine

首先是大名鼎鼎的goroutine(在官方中文文档里翻译成go程,乐),goroutine可以理解为轻量级的线程,开销很小,相对于线程并发能力更强,在go中的声明也很方便,只需要 go f(x, y, z)即可。一个小栗子

	var arr [100]int
	var wg sync.WaitGroup
	wg.Add(2)
	go func(idx int) {...
	}(0)
	go func(idx int) {...
	}(50)
	wg.Wait()

这样可以很快地将数组初始化为0-99(乐),总的来说,通过goroutine可以做到很多有意思的事情

Channel

go的channel也是很强大的一个特性,通过channel可以实现不同线程间的通信以及同步化。

channel也可以选择是否设置缓冲区、如果设置了缓冲区可以一定程度上异步执行。

同时当channel缓冲区已经满了的话,channel的写端将进行阻塞,当channel的缓冲区是空的话,channel的读端将阻塞,同时channel可以不仅仅有一个读写端,可以是一个写端、多个读端。

感觉编写并发代码对功力的要求还是比较高的,不然很容易写出死锁(乐)、或者panic还有注意不要写超出channel的缓冲区,不然会panic

一个例子

	for i := 0; i < 2; i = i + 1 {
		go func(idx int) {
			for im := range ch1 {
				fmt.Printf("go %d :%d\n", idx, im)
			}
		}(i)
	}

Lock

我们喜闻乐见的锁,很经典的并发控制方式,锁编写正确可以保证并发的安全性,但是如果不慎很有可能造成比较不太好的bug

waitGroup

waitGroup采用计数的方式,感觉像是信号量,大概就是Add会增加计数,Done会计数减一,Wait会阻塞到计数器为0,这样可以避免goroutine由于函数结束而被迫终止的情况,一个例子如下

	var wg sync.WaitGroup
	wg.Add(2)
	go func(idx int) {
        ...
	}(0)
	go func(idx int) {
            ...
	}(50)
	wg.Wait()

小结

初步了解了go的并发方式,由于刚开始,感觉了解并不深入,还需要再下功夫

依赖管理

GOPATH

前段时间刚入坑时被这个东西折磨了一段时间,GOPATH的管理方式实际上是很不灵活的,在这种模式下工程的开发路径是固定的,于是自然就被淘汰了。由于本人对c++比较熟悉(习惯随便建文件夹,乐),感觉这种模式很奇怪,很不灵活。

Go Vendor

相对于GOPATH灵活性提高了一些,但还是不够

Go mod

Go mod通过配置文件go.mod描述依赖、代理管理依赖库、本地工具进行操作,用go mod显然舒服了很多 灵活性强了很多。

小结

项目经验并不是很丰富,很多的地方并不能切身体会,但基本的逻辑是清晰的。