这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战
众所周知,go语言提供了一种特殊的特性-协程。一个协程就是一个可以独立并且同时跟程序中的其他协程执行的函数或者方法。或者换一种说法,go语言中的每个并发执行的活动都被认为是协程。你可以认为是,一个协程像一个轻量的线程。创建协程的代价远远小于线程。每个程序至少包含一个单协程,这个协程是主协程。所有协程都是工作在主协程下,如果主协程终止了,当前程序的所有协程也终止了。协程一直是工作在后台。
如何创建一个协程
你可以非常简单地创建一个协程,通过使用go关键字作为函数或者方法调用的前缀,就像下面的语法展示的那样:
语法
func name(){
// statements
}
// using go keyword as the
// prefix of your function call
go name()
例子
// Go program to illustrate
// the concept of Goroutine
package main
import "fmt"
func display(str string) {
for w := 0; w < 6; w++ {
fmt.Println(str)
}
}
func main() {
// Calling Goroutine
go display("Welcome")
// Calling normal function
display("GeeksforGeeks")
}
输出
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
GeeksforGeeks
在上面的例子中,我们简单创建一个 display() 方法,然后使用两种不同的方式调用了这个函数,第一种是协程,例如go display("Welcome"),另一种是普通的函数,例如display("GeeksforGeeks")。但是存在一个问题,这里只展示了普通函数的结果,协程方式的结果没有展示。因为当一个新的协程执行后,协程可以立刻返回了。协程的控制不会等待它完成执行,就像普通的函数,它们总是在协程调用后,移动到下一行执行,并且忽略协程返回的值。因此,为了合理地执行协程,我们在程序中做了一些修改:
修改后的案例
// Go program to illustrate the concept of Goroutine
package main
import (
"fmt"
"time"
)
func display(str string) {
for w := 0; w < 6; w++ {
time.Sleep(1 * time.Second)
fmt.Println(str)
}
}
func main() {
// Calling Goroutine
go display("Welcome")
// Calling normal function
display("GeeksforGeeks")
}
输出
Welcome
GeeksforGeeks
GeeksforGeeks
Welcome
Welcome
GeeksforGeeks
GeeksforGeeks
Welcome
Welcome
GeeksforGeeks
GeeksforGeeks
我们在程序中增加了一个 Sleep() 方法,让主协程在1s内新协程执行中睡一秒,打印了"welcome",然后1s后主协程重新调度就终止了,然后运行了操作。这样,协程和普通函数都可以并发执行。
Advantages of Goroutines协程优势
- 协程比线程更轻量。
- 协程保存在栈中,栈的容量可以根据程序的需求增长或者缩减。但是在线程中,栈的容量是固定的。
- 协程可以通过channel管道的方式来通信,并且这些管道是特殊设计来当访问到共享内存时使用协程来避免竞态条件
- 假设一个程序有一个线程,然后那个线程有很多关联的协程。如果任何一个协程由于资源需求阻塞了线程,那么所有剩下的协程将会分配给一个最新创建的系统线程。所有这些细节都隐藏在编程者后面。
Anonymous Goroutine匿名协程
在go语言中,你也可以启动一个协程来作为一个匿名函数或者换句话说,你可以创建一个匿名协程简单使用go关键字作为函数前缀就像下面展示的那样:
语法
// Anonymous function call
go func (parameter_list){
// statement
}(arguments)
例子
// Go program to illustrate how
// to create an anonymous Goroutine
package main
import (
"fmt"
"time"
)
// Main function
func main() {
fmt.Println("Welcome!! to Main function")
// Creating Anonymous Goroutine
go func() {
fmt.Println("Welcome!! to GeeksforGeeks")
}()
time.Sleep(1 * time.Second)
fmt.Println("GoodBye!! to Main function")
}
输出
Welcome!! to Main function
Welcome!! to GeeksforGeeks
GoodBye!! to Main function\