Go学习笔记(day2) | 青训营笔记

82 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第2天

笨人纯小白,笔记包括一些上课学到的知识和课外总结的内容,如有错误请指正!

四、Golang并发编程

在Go语言编程中你不需要去自己写进程,线程,协程,你的技能包里只有一个技能-goroutine,当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,再开启一个goroutine去执行这个函数就可以了,就是这么简单粗暴。

4.1 使用goroutine

Go语言中使用goroutine非常简单,只需要在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine。

一个goroutine必定对应一个函数,可以创建多个goroutine去执行相同的函数。

    一个函数,一般定义成一个要做的任务

4.2 启动goroutine示例

    func hello() {
	fmt.Println("Hello Goroutine!")
    }
    func main() {
	hello() //这是我们一般执行代码的逻辑
	fmt.Println("main goroutine done!")
    }

接下来我们需要,用goroutine启动一个线程去完成hello任务:

    func main() {
	go hello() // 加go关键字,启动另外一个goroutine线程去执行hello函数
	fmt.Println("main goroutine done!")
    }

如果执行了上述代码你就会发现,执行结果只打印了main goroutine done!,并没有打印Hello Goroutine!。为什么呢?

答: Go开启一个线程去执行hello任务之后,然后直接就print输出main goroutine done!,主进程就结束了,然后所属它的子进程也会被杀死。因为创建线程有时间开销,代码执行的速度是非常快的。所以子线程还没来得及打印Hello Goroutine!就被杀死了。

所以我们要想办法让main函数等一等hello函数,最简单粗暴的方式就是time.sleep了。

    func main() {
	go hello() // 启动另外一个goroutine去执行hello函数
	fmt.Println("main goroutine done!")
	time.Sleep(time.Second)
    }

执行上面的代码你会发现,这一次先打印main goroutine done!。然后紧接着打印Hello Goroutine!。

4.3 main优雅谢幕(sync.WaitGroup)

sync.WaitGroup方法如下: image.png 上面的sleep去等子线程结束后,主进程再退出,存在可能等多了,可能等少了这种情况,因此需要有一种“优雅”的方式去结束主进程(因此下面使用了sync.WaitGroup实现main的优雅谢幕)。

    var wg sync.WaitGroup //声明一个变量wg
    func hello(i int) {
        defer wg.Done() // goroutine结束,wg-=1
        fmt.Println("Hello Goroutine!", i)
    }
    func main() {
        for i := 0; i < 10; i++ {
            wg.Add(1) // 启动一个goroutine,wg+=1
            go hello(i)
        }
        wg.Wait() // 当监听到wg为0(即所有goroutine结束了),则执行后面的逻辑
    }

除此之外,上面还利用for循环,生成了多个goroutine。值得注意的是: 上面的10个goroutine只要有一个线程发生了阻塞,这个主进程都不会退出,这样会浪费大量资源,一定要确保goroutine不会发生阻塞。