goroutine与channel

x33g5p2x  于2021-11-15 转载在 Go  
字(1.7k)|赞(0)|评价(0)|浏览(430)

启动goroutine

在golang中,一个活动单元被称为goroutine,通过go关键字来启动一个goroutine并立刻返回。

f()		// 调用f(),并等待结果
go f()	// 新建一个调用f()的goroutine,不用等待

main函数运行在主goroutine中,当main函数返回时,所有的goroutine都将终结,进程将退出,释放所有资源。

goroutine的粒度是一个函数,这个函数无需实现任何接口,也无需绑定到任何类中。我们也可以通过go关键字直接运行一个匿名函数,就像下面这样

go func() {
	// do something async
}()

使用channel(通道)在不同的goroutine中通信

ch := make(chan int)

上面的代码创建了一个chan int类型的通道。

通道有三个操作,发送、接收和关闭。

ch <- x				// 将x发送给ch通道
x, ok = <- ch		// 从ch通道中接收一个值,并赋值给x。 ok为false时表示通道已关闭,此时的x为零值。
<- ch				// 从ch通道中接收一个值,并丢弃
close(ch)			// 关闭通道

向已关闭的通道发送消息将会导致应用宕机,从已关闭的通道中读取消息的话,后续的所有操作都顺畅进行,只是获取到的是零值。

一个管道的demo

下面的demo中,将创建三个goroutine,第一个goroutine负责生产数字,第二个goroutine负责做平方,第三个goroutine负责打印数字,它们之间使用两个通道进行通信,这比较像linux中的pipeline(管道)。当第一个goroutine生产10个数字时候,通道关闭,当第二个goroutine发现第一个通道关闭后,也关闭第二个通道。

func main() {

	naturals := make(chan int)
	squares := make(chan int)

	go func() {
		for i := 0; i < 10; i++ {
			naturals <- i
			time.Sleep(time.Millisecond * 100)
		}
		close(naturals)
	}()

	go func() {
		for {
			x, ok := <-naturals
			if !ok {
				close(squares)
				break
			}
			squares <- x * x
		}
	}()

	for x := range squares {
		fmt.Println(x)
	}
	fmt.Println("done")
}

值得注意的是,第二个goroutine是手动的捕获到了通道已关闭的时机,而第三个goroutine则借助了range,当通道关闭时(即接收到的第二个参数为false时),循环自动结束。

注意:当通道未关闭,并且没有发送者继续向通道发送消息时,range函数会阻塞死。

单向通道

我们可以通过 chan<-来表示一个只能发送的通道,通过<-chan来表示一个只能接收的通道。

我们将上面的代码改造一下,通过go关键字来调用一个命名函数,并使用单向通道:

func generateNumbers(outputCh chan<- int) {
	for i := 0; i < 10; i++ {
		outputCh <- i
		time.Sleep(time.Millisecond * 100)
	}
	close(outputCh)
}

func squareNumbers(inputCh <-chan int, outputCh chan<- int) {
	for x := range inputCh {
		outputCh <- x * x
	}
	close(outputCh)
}

func printNumbers(inputCh <-chan int) {
	for x := range inputCh {
		fmt.Println(x)
	}
}

func main() {

	naturals := make(chan int)
	squares := make(chan int)

	go generateNumbers(naturals)

	go squareNumbers(naturals, squares)

	printNumbers(squares)

	fmt.Println("done")
}

相关文章

最新文章

更多