go语言学习的几个概念:接口、协程、通道、WaitGroup

因为儿子在学校自学go语言编程,时不时为他解答一些问题,也让很长时间没写过代码的我不懂的时候重温一下编程知识。虽然语言是新的,但好像编程思维还在。也试图通过一些易理解的例子来解释其中一些概念,虽然不会很准确,但也许也可以促进理解。

关于接口的解释

type <接口名称> interface {
<方法列表>
}
这是go语言中对接口的定义语法,其实所有语言关于接口的定位都是一致的,定义方式也是大同小异。用下面的例子来解释“接口是什么,为什么要定义接口”:

以衣服为例:衣服要有两个袖子、五粒扣子。只有符合这个标准的衣服人才能穿进去,这个可以理解为接口(标准)。然后有白色衬衣、棉袄、夹克不同的类型,不同衣服的材料不一样,颜色不一样,厚度不一样,长度不一样。这些不同衣服都要符合上面那个接口标准(两个袖子和五粒扣子),才能有人买了穿。

然后就是不同人在不同季节买衣服的时候,会根据实际需要买不同的衣服。但不同人在跟别人交流的时候,他可能只会说,我穿了衣服。如某个场所要求进入的人只要穿了衣服就行,而不需要管你穿什么衣服。

另一个手机充电接口的例子:Adroid手机的充电接口现在都基本统一成typec接口了,所以相互之间可以通用,但不同的充电器实现方式不一样,有快速充电有多少伏充电。苹果手机的充电器无法给华为手机充电,那是因为接口不一样。

程序直接相互调用的时候,只需要使用接口来调用,不需要知道里面实现的细节。一个系统会有很多模块组成,不同模块实现不同功能,这些模块之间就要定义接口规范。在不同场景下,功能实现会有差别,但模块跟模块之间的调用方式不变,这就依赖于接口规范。

上升到更高层面就是架构设计需要考虑的问题,不管我怎么变,我们的交互方式不要变。所以一个系统的架构设计中,接口就是其很重要的一部分。

关于协程和通道的解释

为了简单理解go语言中的协程和通道的概念,用公路上的行驶车辆来做比方。

Go语言的协程概念就是一个轻量级的线程,它不依赖于操作系统的调度,只依赖于当前运行的进程或线程。我理解的进程(主线程)和线程是依赖于操作系统的调度机制,线程都是通过CPU分时调度的。对协程而言,其实也是线程在应用层的分时调度,而不是CPU的分时调度,如果线程消亡,这个线程中启动的协程就会自动消亡。

下面这个公路的例子,我们需要先忽略这个分时调度的概念,暂时认为是可以同时运行的,因为不同辅道的车辆是可以同时行驶的,而实际上的协程中的内容是分时处理的,抛开“分时”这个概念来理解协程和通道,可能更容易。

某一段公路有三条道(一条主道,左右各一条辅道),正常情况下三条道的车辆都各自通行,这里辅道一定是依赖于主道的存在的,没有主道就谈不上辅道的概念,即辅道源于主道、终于主道。

由于道路容量限制当两条辅道上各有100辆车在行驶时,为了减轻两条辅道的行驶压力,有一名交警在进行指挥,左边辅道排在奇数位和右边辅道排在偶数位的车辆需要转入主道,而且需要依次轮流转入主道,同时需要对主道进行交通管制。

用个代码例子来解释:
var ch chan int //两条辅道的轮流通行指示,辅道上的车辆只能依次通行。
var exit chan string //在两条辅道进行交通指挥时,对主通道进行交通管制的指示。

func print1() {//左边辅道上有100辆车,奇数位车辆需要进入主道
for i := 0; i <= 100; i++ {
ch <- 1//左边辅道在交警指挥下通行,右边辅道禁止通行。
if i%2 == 1 {
fmt.Println(i)
}
}
}

func print2() {//右边辅道上有100辆车,偶数位车辆需要进入主道
for i := 0; i <= 100; i++ {
<-ch//右边辅道在接受到交警指挥后通行,左边辅道就禁止通行。
if i%2 == 0 {
fmt.Println(i)
}
if i == 100 {//当全部符合条件的车辆转入主道后,主道管制解除
exit <- "x"//主通道管制解除指示
}
}
}

func main() {
ch = make(chan int) //创建一个channel,作为两条辅道的交通指示
exit = make(chan string)//创造一个channel,主道的管制指示
go print1()
go print2()
<-exit//主通道管制解除
}

关于WaitGroup的解释

sync.WaitGroup类型内部维护一个计数器,某个Go协程调用Wait方法后会被阻塞,直到WaitGroup对象的计数器变为0。
下面这段代码跟上面这节程序的功能是类似的,只是用WaitGroup实现了“通道”的功能,让主线程等待其他协程运行完成。
var ch chan int
var wg sync.WaitGroup

func print1() {
for i := 0; i <= 100; i++ {
ch <- 1
if i%2 == 1 {
fmt.Println(i)
}
}
wg.Done()
}

func print2() {
for i := 0; i <= 100; i++ {
<-ch
if i%2 == 0 {
fmt.Println(i)
}
}
wg.Done()
}

//主线程:当主线程执行完毕后会直接退出,协程也会退出,尽管它可能没执行完毕
//可以使用sync.WaitGroup可以实现主线程等待协程执行完毕
func main() {
ch = make(chan int)
wg.Add(2)
go print1() //表示开始一个协程,go语言的优势就在于开启协程所占用的空间非常小
go print2()
wg.Wait()
}

OVER!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容