温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

go中的Golang协程怎么分析

发布时间:2022-01-17 16:06:26 来源:亿速云 阅读:231 作者:kk 栏目:大数据

这篇文章跟大家分析一下“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循环,就不会报错了!虽然不是符合实际开发代码规范,但是可以使用,能够解释原理。

go是什么

golang是一种编译语言,可以将代码编译为机器代码,编译后的二进制文件可以直接部署到目标机器而无需额外的依赖,所以golang的性能优于其他的解释性语言,且可以在golang中使用goroutine来实现并发性,它提供了一个非常优雅的goroutine调度程序系统,可以很容易地生成数百万个goroutine。

关于go中的Golang协程怎么分析就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下亿速云网站!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI