August Rush

一个还在努力成长的小火汁!

游龙当归海,海不迎我自来也。

We create our own demons.

You can reach me at augustrush0923@gmail.com
Go语言基础-Goroutine
发布:2024年01月22日 | 作者:augustrush | 阅读量: 1005

协程goroutine

Goroutine 是 Go 程序中最基本的并发执行单元。每一个 Go 程序都至少包含一个 goroutine——main goroutine,当 Go 程序启动时它会自动创建。

在Go语言编程中你不需要去自己写进程、线程、协程,你的技能包里只有一个技能——goroutine,当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,开启一个 goroutine 去执行这个函数就可以了,就是这么简单粗暴。

开启一个goroutine

在Go中开启一个协程非常简单,只需在一个普通函数前面加上一个go关键字,就可以开启一个goroutine

// 执行一个函数
func()

// 开启一个协程执行这个函数
go func()

goroutine基本使用

一个Go程序的入口通常是main函数,程序启动后,main函数最先运行,我们称之为main goroutine

main中或者其下调用的代码中才可以使用go + func()的方法来启动协程。

main的地位相当于主线程,当main函数执行完成后,这个线程也就终结了,其下的运行着的所有协程也不管代码是不是还在跑,也得乖乖退出。(主线程结束,代表整个程序执行结束,所有资源都会回收。)

package main

import "fmt"

func mytest() {
    fmt.Println("hello, go")
}

func main() {
    // 启动一个协程
    go mytest()
    fmt.Println("hello, world")
}

这段代码运行完,只会输出hello, world,而不会输出hello, go(因为协程的创建需要时间,当hello, world打印后,协程还没来得及创建并执行)

可以通过time.Sleep来阻塞主线程,来实现协程的创建并执行。

多个goroutine并行执行

package main

import (
    "fmt"
    "time"
)

func main() {
    go goRoutine("协程1号")
    go goRoutine("协程2号")
    time.Sleep(5 * time.Second)
}

func goRoutine(message string) {
    for i := 0; i < 10; i++ {
        fmt.Printf("%v: %v\n", i, message)
    }
    time.Sleep(10 * time.Millisecond)
}

执行结果:

$ go run main.go
0: 协程2号
1: 协程2号
2: 协程2号
3: 协程2号
4: 协程2号
5: 协程2号
6: 协程2号
7: 协程2号
8: 协程2号
9: 协程2号
0: 协程1号
1: 协程1号
2: 协程1号
3: 协程1号
4: 协程1号
5: 协程1号
6: 协程1号
7: 协程1号
8: 协程1号
9: 协程1号

WaitGroup

当主线程运行完后,所有goroutine都会停止。但在实际开发中,我们无法预知什么时候所有goroutine都会执行完毕。可以通过sync包的WaitGroup来实现让主程序等待所有goroutine执行行完再结束。

// var 实例名 sync.WaitGroup 
var wg sync.WaitGroup

实例化完成后,就可以使用它的几个方法:

  • Add: 初始值为0,你传入的值会往计数器上加,这里直接传入你开启协程的数量
  • Done: 当某个协程完成后,可调用此方法,会从计数器上减一,通常可以使用defer来调用。
  • Wait: 阻塞当前进程,直到实例里的计数器归零。
package main

import (
    "fmt"
    "sync"
)

func worker(x int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Printf("worker %d: %d\n", x, i)
    }
}

func main() {
    var wg sync.WaitGroup

    wg.Add(2)
    go worker(1, &wg)
    go worker(2, &wg)

    wg.Wait()
}


  • 标签云

  • 支付宝扫码支持一下

  • 微信扫码支持一下



基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建

京ICP备20007446号-1 & 豫公网安备 41100202000460号

网站地图 & RSS | Feed