Golang goroutine

Golang goroutine教程

go 里面,每一个并发执行的活动称为 goroutine。goroutine 可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小,每个 goroutine 的堆栈只有几 kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),所以 go 程序从语言层面支持了高并发。

在 Golang 中,我们也可以将 goroutine 称为协程,当一个程序启动的时候,只有一个 goroutine 来调用 main 函数,称它为主 goroutine,新的 goroutine 通过 go 语句进行创建。

并发模型

并发目前来看比较主流的就三种:

模型 描述
多线程 每个线程一次处理一个请求,线程越多可并发处理的请求数就越多,但是在高并发下,多线程开销会比较大。
协程 无需抢占式的调度,开销小,可以有效的提高线程的并发性,从而避免了线程的缺点的部分。
基于异步回调的IO模型 说一个熟悉的,比如 nginx 使用的就是 epoll 模型,通过事件驱动的方式与异步IO回调,使得服务器持续运转,来支撑高并发的请求。

Golang协程解

语法

go func()

参数

参数 描述
go 创建协程使用的关键字。
func() 协程的函数实体。

说明

要创建一个协程,只需要在函数前面加上 go 关键字即可。

案例

创建协程

使用 go 关键字创建协程

package main import ( "fmt" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") go fun1() fmt.Println("Over") } func fun1(){ fmt.Println("Call fun1") }

程序运行后,输出如下图所示:

23_Go语言goroutine.png

我们看到,我们使用了 go 创建了一个协程 fun1,但 fun1 里面的输出并没有被输出,这是因为,协程还没被执行,main 函数已经退出了,现在,我们修改程序如下:

package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") go fun1() fmt.Println("Over") time.Sleep(time.Duration(5)*time.Second) } func fun1(){ fmt.Println("Call fun1") }

程序运行后,输出如下图所示:

24_Go语言goroutine.png

我们看到,此时协程被执行了,因此,我们需要协程被执行,main 函数必须不能运行后立即退出。

创建多个协程

使用 go 关键字创建多个协程

package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") go fun1() go fun1() go fun1() fmt.Println("Over") time.Sleep(time.Duration(5)*time.Second) } func fun1(){ fmt.Println("Call fun1") }

程序运行后,输出如下图所示:

25_Go语言goroutine.png

我们看到,我们使用了 go 创建了三个协程 fun1,这三个协程是互不影响的。

直接创建协程

使用 go 关键字直接创建多个协程

package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") go func(){ fmt.Println("Hello World") }() go func(){ fmt.Println("Hello HaiCoder") }() go func(){ fmt.Println("haicoder.net") }() time.Sleep(time.Duration(5)*time.Second) }

程序运行后,输出如下图所示:

26_Go语言goroutine.png

这次,我们直接使用 go 加上函数体创建了三个协程,这里一定要注意,在协程的最后一定要使用 () 才表示调用该协程,如果没有 () 那么协程是不会执行的。

Golang goroutine总结

在 go 里面,每一个并发执行的活动称为 goroutine。goroutine 可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小,每个 goroutine 的堆栈只有几 kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),所以 go 程序从语言层面支持了高并发。

在 Golang 中,我们也可以将 goroutine 称为协程,当一个程序启动的时候,只有一个 goroutine 来调用 main 函数,称它为主 goroutine,新的 goroutine 通过 go 语句进行创建。