这篇文章跟大家分析一下“go中的Golang协程怎么分析”。内容详细易懂,对“go中的Golang协程怎么分析”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“go中的Golang协程怎么分析”的知识吧。
1. Hello Goroutine
package main
import (
"fmt"
)
func main() {
go sayHello()
}
func sayHello() {
fmt.Println("Hello Goroutine !!!")
}
go语言开启协程的关键词是go,后面接着一个匿名函数或者一个自定义的函数,但是,如果运行了上面的代码,你会发现终端并没有输出‘Hello Gorounitn !!!’,为什么呢?
上面的代码并没有问题,不会执行错误,之所以不会输出是因为在golang语言中,main函数也是一个协程,而且是主协程。什么意思呢?就是每当你执行go项目时(必需有main函数,而且只能有一个main函数),会首先开启一个main函数的主协程,这个主协程的执行时间会影响到子协程,子协程就是go关键词加函数,如果主协程先执行完毕,那么子协程就不会被执行,所以 我把代码改成这样:
package main
import (
"fmt"
"time"
)
func main() {
go sayHello()
time.Sleep(time.Second)
}
func sayHello() {
fmt.Println("Hello Goroutine !!!")
}
输出:
Hello Goroutine !!!
sleep 1s,等待子协程执行,所以会有输出。
2. WaitGroup
等待子协程执行用睡眠的方式不符合实际开发,所以sync包下的WaitGroup可以解决这个问题,代码:
package main
import (
"fmt"
"sync"
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(2)
go sayHello(wg)
go sayHello2(wg)
wg.Wait()
}
func sayHello(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Hello Goroutine !!!")
}
func sayHello2(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Hello Golang !!!")
}
解释:在main函数里声明一个wg变量,wg.Add(2)的意思是我这里有两个协程要执行,所以传入2,如果你有n个协程呢?那就传入n,wg.Done()相当与wg.Add(-1)就是该子协程执行完毕。wg.Wait()就是告诉主协程要等待子协程执行完毕才能退出。
3. Channel
channel,又叫管道,在go里面的管道是协程之间通信的渠道,类似于咱们常用的消息队列。
package main
import (
"fmt"
"strconv"
)
func main() {
ch := make(chan string)
for i := 0; i <= 10; i++ {
go demo(ch, "Hello Channel"+strconv.Itoa(i))
}
for d := range ch {
fmt.Println(">>>>>>>>>>>>>>", d)
}
}
func demo(c chan string, data string) {
c <- data
}
简单说明一下,这里就是实例化了一个string类型的管道,在调用函数的时候会把管道当作参数传递过去,然后在调用函数里面我们不输出结果,然后把结果通过管道返还回去,然后再主线程里面我们通过for range循环依次取出结果!
但是这个程序是有bug的,在程序的运行的最后会出现一个fatal error,提示所有的协程都进入睡眠状态,死锁!
go的管道默认是阻塞的(假如你不设置缓存的话),你那边放一个,我这头才能取一个,如果你那边放了东西这边没人取,程序就会一直等下去,死锁了,同时,如果那边没人放东西,你这边取也取不到,也会发生死锁!
如何解决这个问题呢?标准的做法是主动关闭管道,或者你知道你应该什么时候关闭管道, 当然你结束程序管道自然也会关掉!针对上面的演示代码,可以这样写:
var (
i int
)
for d := range ch {
fmt.Println(">>>>>>>>>>>>>>", d)
//
if i >= 10 {
close(ch)
}
i++
}
因为我们明确知道总共会输出11个结果,所以这里简单做了一个判断,大于等于10就关闭管道退出for循环,就不会报错了!虽然不是符合实际开发代码规范,但是可以使用,能够解释原理。
golang是一种编译语言,可以将代码编译为机器代码,编译后的二进制文件可以直接部署到目标机器而无需额外的依赖,所以golang的性能优于其他的解释性语言,且可以在golang中使用goroutine来实现并发性,它提供了一个非常优雅的goroutine调度程序系统,可以很容易地生成数百万个goroutine。
关于go中的Golang协程怎么分析就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下亿速云网站!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。