go语言,chanel and goroutine(golang)(三)

"Do not communicate by sharing memory; instead, share memory by communicating." ——effective go
上面这条go语言的哲学中的理念反映到具体的代码中,就是go语言所提供的channel,这是一种强大易用的机制,单稍不留神,就会出现问题

Channel简介

让我们先来写一个简单的channel例子:

package main

func main() {
	fooChan := make(chan int, 1)
	fooChan <- 1
	val := <-fooChan
	print(val)	
}

这里我们用make创建了fooChan这个可以缓存1个int单位的chanel,将整数1加入到fooChan,并在下一条指令中取出并输出。在go语言中,我们可以创建built-in类型的channel,也可以创建custom-defined类型的channel
这里要注意这段代码:

fooChan := make(chan int, 1)

make的第二个参数表示这个channel可以缓存多少条输入,如果我们这样写:

fooChan := make(chan int)

则表示创建了一个没有缓存的channel,当我们向一个没有缓存的channel中写入值的时候,我们的线程将会被阻塞。

goroutine简介

在多核CPU越来越普及的今天,为了在充分利用多核优势的同时减轻多线程编程的复杂度,go语言为我们提供了goroutine这个go语言引以为傲的工具。简单来讲,go语言支持语言层面的多线程编程,这是非常难得的,而且是划时代的。
下面是使用goroutine的一个例子:

package main
import "sync"
func main() {
	var wait sync.WaitGroup
	wait.Add(1)
	go func(){
		print("Hello Goroutine")
		wait.Done()
	}()
	wait.Wait()
}

注意go func(){...}()这段代码,这是在go语言中启动一个goroutine的方式,使用go关键字后面接一个函数,表示需要goroutine来运行的函数,这个函数可以接收任意参数,在这里我们使用一个无参数的函数。
在goroutine中的代码是异步执行的,而且一般情况下是另一个工作线程去执行其中的代码,我们使用一个WaitGroup来让主线程停止在Wait函数中,直到工作线程执行完print操作后,主线程再结束程序。

channel和goroutine结合使用

channel和goroutine最直接的联合使用方式是生产-消费模式:

package main
import "time"
func main() {
	outputs := make(chan string)
	go func(){
		for {
			outputs <- "goroutine 1\n";
			time.Sleep(time.Second)
		}
	}()
	go func() {
		for {
			outputs <- "goroutine 2\n";
			time.Sleep(time.Second)
		}	
	}()	
	for s := range outputs{
		print(s)
	}
}

主线程会一直执行for s := range outputs这行代码,并输出其他goroutine写入的数据。用这样的方法,我们可以将一个很复杂的计算进行拆分,分配给不同的CPU内核去执行以提高总体执行效率。

下一步

channel和goroutine的简单使用就这么多,但是其中有很多需要注意的地方在本篇文章中没有提及,我会在后面的文章中详细解析。

posted @ 2017-04-16 14:16  devgl  阅读(1003)  评论(0)    收藏  举报