化茧成蝶:Go在FreeWheel服务化中的实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

Go语言的并发模型以其简练而独特的设计、对开发者的简洁易用以及高性能而区分于其他的传统开发语言,如C++、Java等。Go语言提供了围绕着Goroutine、Channel为核心概念的并发特性,正确地理解和使用它们,不仅可以避免程序出现一些并发或同步方面难以预知的运行问题,也有助于开发者更优雅地设计出利用Go并发模式的模块及系统。

本文主要针对Go并发模型下的Channel的使用,结合实际开发中的体会做一下总结,希望借此帮助接触Go语言不久的开发者们,正确掌握Channel这一重要并发特性的打开方式,并在实际项目中自如地使用Go语言的并发特性,开发出正确而高效的程序。

Channel概述

开始学习Go的同学们一定都知道Channel了,这可以说是Go语言提供的最亮眼的一个语言特性了。顾名思义,Channel即通道,是Go语言中用来在不同Goroutine之间进行通讯的管道。Go语言中的各种类型,从原生类型Int、 Int64、 String、Map等,到Struct、Interface、Pointer,都可以用Channel来在各个Gouroutine之间传递。

Channel的声明和初始化非常简单,同时需要指定Channel中所传递的数据的类型:

        var ch1 chan interface{} //声明一个传递类型为interface{}的channel
        ch2 := make(chan int)   //创建一个传递的数据类型为int的unbuffered
        channel
        ch3 := make(chan string,  5) //创建一个传递string类型的buffered
        channel, buffer的容量为5

这里要注意的是,已声明但是没有初始化的Channel,它的值是nil, nil的Channel无论发送和读取都会阻塞。后面的章节会列出几种使用Channel时的坑,并一一说明。

往Channel中写入及读取:

        ch1 <- x  //往Channel中写入值
        y = <- ch2 //从channel中取出值
        <- ch3 //取值并丢弃
        close(ch3) //关闭channel

以上是Channel的定义和基本使用方式,Golang官方以及中文社区都有大量的资料说明。在这里要展开深入讨论的是Channel的正确打开方式。因为仅仅了解了Channel怎样定义,怎样写入和读取,仍然不足以让你写出正确使用Channel的Go语言程序。下面一部分,我们会从Channel的使用细节和实例,来看看它的正确打开方式是怎样的,在实际使用中有哪些坑需要注意。