使用go关键字可以为一个函数创建goroutine,相当于其它编程语言的多协程操作
启动goroutine
可以发现go func中的程序并不影响后面的代码执行,但main函数执行完毕后goroutine也会被关闭,无论剩下的代码是否执行完毕。
示例
package main
import (
"fmt"
"time"
)
func main() {
go func() {
time.Sleep(time.Second)
fmt.Println("2")
}()
fmt.Println("1")
// 添加等待时间,防止goroutine因为程序结束而关闭
time.Sleep(time.Second * 2)
}运行结果
1
2
goroutine池
当需要处理的任务过多时,每个任务都开启一个goroutine会导致性能开销过大,可以通过goroutine池实现goroutine的重复使用。步骤如下:
- 确定一个
worker函数,这是程序的主要工作函数 - 定义若干个管道,可以在
worker和主程序之间传输数据 - 通过循环和
go关键字启动若干个worker,并且worker持续从管道中获取数据,此时woker保持阻塞状态 - 确定管道关闭条件,管道关闭后,
worker自动关闭,程序结束
这样就保证了所有worker都不会立马被关闭,而是继续从管道中获取数据并处理,直到管道被关闭。
实现代码
// 定义一个worker
func worker(c chan int){
// 从管道获取数据
for i := range c{
fmt.Printf(i)
}
}
// 主函数
func main(){
// 向worker发送数据的管道
c := make(chan int, 100)
// 创建goroutine池
for i := 0; i < 100; i++{
go worker(c)
}
// 发送数据
for j := 0; j < 10000; j++{
c <- j
}
// 关闭管道,worker自动退出
close(c)
}