一、前言
新年学新语言Go系列文章已经完结,用了最简单的例子去了解Go基础语法,但Go最牛B的是它对并发的友好支持,每一门语言都有它自己独特的优势,如Java适合大型工程化项目,Python适合做数据分析及运维脚本,而Go最适合用来做高并发的网络通讯,PHP适合快速开发网站,所以有兴趣都可以学习了解一下,编程思路是互通。关于Go并发 新年学新语言Go之一 有一个概略的介绍,这一系列会从最简单一些例子入手,然后穿插介绍一些必要的理论。
二、例子1
执行结果:无任何输出
在函数或方法前面加上关键字 go,它会启动一个goroutine(协程),然后被放在队列中等待调度器来决定什么时候执行这个goroutine。然而main这个主协程已经执行完成,Go进程都Over了,新创建的goroutine还没有被调度执行,所有大概率是无任何输出。
操作系统理论讲的是一个进程至少要包含一个线程,随着进程的启动会创建第一个线程,这个称为主线程,goroutine也类似。
执行结果:Go,Goroutine!
加上time.Sleep,会让main所有的goroutine进行暂停(进入Gwaiting状态),然后println("Go,Goroutine!") 这个goroutine就有可能被调度执行了,但这也并不是很保险,可以换成调用runtime.Gosched()来暂停当前goroutine,让其它goroutine有机会运行。
三、例子2
执行结果:Hello,Qingcai18036!
执行结果说明了在name = "Qingcai18036"执行之后,上面那个go函数才得以被调度执行。下面更换一下最后两条语句顺序
执行结果:Hello,Qingcai!
这是因为在改变name变量的值之前,就给了go函数执行的机会了。
四、例子3
执行结果:
这是因为for里的迭代变量name虽然会依次被赋予qingcai1,qingcai2,qingcai3,但这里并发执行的go函数是在for语句执行完才执行,因为for遍历非常快,这时name已经指向 qingcai3了。
执行结果
将time语句放在循环内就可以在迭代完成之前给每个go函数一个执行的机会,但这也不保险
执行结果:
让go函数中使用的name不会受外部变量的影响,go函数可以有参数声明,然后将迭代变量name做为参数传递给go函数,因为name变量的类型是string它是非引用类型,我们把值做为参数传给函数时该值会被复制,对于引用类型这样处理就没有作用了,另外可以看到结果的顺序是乱的,因为调度器什么时候执行goroutine是不确定的。
注:相对于其它语言,Go启动一个协程语法实在是太简单了!简单就是好。