For-learning-Go-Tutorial

Go语言是谷歌2009发布的第二款开源编程语言

Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。

因而一直想的是自己可以根据自己学习和使用Go语言编程的心得,写一本Go的书可以帮助想要学习Go语言的初学者快速入门开发和使用!

Channel

Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯(communication).

Channel用于数据传递或数据共享,其本质上是一个先进先出的队列,使用Goroutine 和channel进行数据通讯简单高效,同时也线程安全,多个Goroutine可同时修改一个Channel,不需要加锁。

管道是一系列由channel联通的状态(stage),而每个状态是一组运行相同函数的Goroutine。在每个状态的Goroutine上:

  • 通过流入(inbound)channel接收上游的数值.
  • 运行一些函数来处理接收的数据,一般会产生新的数值.
  • 通过流出(outbound)channel将数值发给下游.

每个语态都会有任意个流入或者流出channel,除了第一个状态(只有流出channel)和最后一个状态(只有流入channel)。第一个状态有时被称作源或者生产者;最后一个状态有时被称作槽(sink)或者消费者。

我们先从简单开始使用内置的make函数,创建一个Channel:

  1. ch := make(chan int)
  2. `

然而每个channel都有一个特殊的类型,也就是channels可发送数据的类型。一个可以发送int类型数据的channel一般写为chan int,一个channel有发送和接受两个主要操作,都是通信行为。一个发送语句将一个值从一个goroutine通过channel发送到另一个执行接收操作的goroutine。发送和接收两个操作都是用<-运算符。

  1. ch <- p // 发送值p到Channel ch中
  2. p := <-ch // 从Channel ch中接收数据,并将数据赋值给p

注意:在channel中箭头的指向是数据的流向.

和map类似,channel也一个对应make创建的底层数据结构的引用。当我们复制一个channel或用于函数参数传递时,我们只是拷贝了一个channel引用,因此调用者何被调用者将引用同一个channel对象。和其它的引用类型一样,channel的零值也是nil。两个相同类型的channel可以使用==运算符比较。如果两个channel引用的是相通的对象,那么比较的结果为真。一个channel也可以和nil进行比较。

Channel类型的定义格式:

  1. ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) Type .

它包括三种类型的定义。可选的<-代表channel的方向。如果没有指定方向,那么Channel就是双向的,既可以接收数据,也可以发送数据。

  1. chan p // 可以接收和发送类型为p的数据
  2. chan<- float64 // 只可以用来发送 float64 类型的数据
  3. <-chan int // 只可以用来接收 int 类型的数据

这里需要注意下:<-总是优先和最左边的类型结合。

使用make初始化Channel,我们还可以设置channel的容量,容量(capacity)代表Channel容纳的最多的元素的数量,代表Channel的缓存的大小。

  1. ch = make(chan int) // 无缓冲 channel
  2. ch = make(chan int, 0) // 无缓冲 channel
  3. ch = make(chan int, 3) // 缓冲 channel容量是3

如果没有设置容量,或者容量设置为0, 说明Channel没有缓存,只有sender和receiver都准备好了后它们的通讯(communication)才会发生(Blocking)。如果设置了缓存,就有可能不发生阻塞, 只有buffer满了后 send才会阻塞, 而只有缓存空了后receive才会阻塞。一个nil channel不会通信。