在 go 里面,每一个并发执行的活动称为 goroutine。goroutine 可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小,每个 goroutine 的堆栈只有几 kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),所以 go 程序从语言层面支持了高并发。
在 Golang 中,我们也可以将 goroutine 称为协程,当一个程序启动的时候,只有一个 goroutine 来调用 main 函数,称它为主 goroutine,新的 goroutine 通过 go 语句进行创建。
并发目前来看比较主流的就三种:
模型 | 描述 |
---|---|
多线程 | 每个线程一次处理一个请求,线程越多可并发处理的请求数就越多,但是在高并发下,多线程开销会比较大。 |
协程 | 无需抢占式的调度,开销小,可以有效的提高线程的并发性,从而避免了线程的缺点的部分。 |
基于异步回调的IO模型 | 说一个熟悉的,比如 nginx 使用的就是 epoll 模型,通过事件驱动的方式与异步IO回调,使得服务器持续运转,来支撑高并发的请求。 |
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")
}
程序运行后,输出如下图所示:
我们看到,我们使用了 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")
}
程序运行后,输出如下图所示:
我们看到,此时协程被执行了,因此,我们需要协程被执行,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")
}
程序运行后,输出如下图所示:
我们看到,我们使用了 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)
}
程序运行后,输出如下图所示:
这次,我们直接使用 go 加上函数体创建了三个协程,这里一定要注意,在协程的最后一定要使用 ()
才表示调用该协程,如果没有 ()
那么协程是不会执行的。
在 go 里面,每一个并发执行的活动称为 goroutine。goroutine 可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小,每个 goroutine 的堆栈只有几 kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),所以 go 程序从语言层面支持了高并发。
在 Golang 中,我们也可以将 goroutine 称为协程,当一个程序启动的时候,只有一个 goroutine 来调用 main 函数,称它为主 goroutine,新的 goroutine 通过 go 语句进行创建。