使用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的重复使用。步骤如下:

  1. 确定一个worker函数,这是程序的主要工作函数
  2. 定义若干个管道,可以在worker和主程序之间传输数据
  3. 通过循环和go关键字启动若干个worker,并且worker持续从管道中获取数据,此时woker保持阻塞状态
  4. 确定管道关闭条件,管道关闭后,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)
}