如何在网上接做网站的小项目,网站建设程序员招聘,互联网保险的特点不包括,广州网站开发定制文章目录 前言一、Goroutine适合的使用场景二、Goroutine的使用1. 协程初体验 三、WaitGroupWaitGroup 案例一WaitGroup 案例二 总结 前言
学习Golang一段时间了#xff0c;一直没有使用过goroutine来提高程序执行效率#xff0c;在一些特殊场景下#xff0c;还是有必须开启… 文章目录 前言一、Goroutine适合的使用场景二、Goroutine的使用1. 协程初体验 三、WaitGroupWaitGroup 案例一WaitGroup 案例二 总结 前言
学习Golang一段时间了一直没有使用过goroutine来提高程序执行效率在一些特殊场景下还是有必须开启协程提升体验的打算整理几篇关于协程的原理的文章和案例结合工作场景将协程使用起来。 一、Goroutine适合的使用场景
并发执行任务 Goroutine 可用于同时执行多个任务提高程序的性能。 非阻塞 I/O 操作 在进行 I/O 操作时可以使用 goroutine 确保其他任务继续执行而不是同步等待 I/O 完成。 事件驱动编程 Goroutine 可用于处理事件如监听 HTTP 请求、处理用户输入等。 并发算法 实现一些需要并行计算的算法通过 goroutine 可以更轻松地管理并发执行的部分。 定时任务 使用 goroutine 和定时器可以实现定时执行的任务。
二、Goroutine的使用
1. 协程初体验
一个 Go 程序的入口通常是 main 函数,程序启动后main 函数最先运行我们称之为 main goroutine。
在 main 中或者其下调用的代码中才可以使用 go func() 的方法来启动协程。
main 的地位相当于主线程当 main 函数执行完成后这个线程也就终结了其下的运行着的所有协程也不管代码是不是还在跑也得乖乖退出。
package mainimport fmtfunc mytest() {fmt.Println(hello, go)
}func main() {// 启动一个协程go mytest()fmt.Println(hello, world)
}因此上面这段代码运行完只会输出 hello, world 而不会输出hello, go因为协程的创建需要时间当 hello, world打印后协程还没来得及并执行
当我在代码中加入一行 time.Sleep 输出就符合预期了。
package mainimport (fmttime
)func mytest() {fmt.Println(hello, go)
}func main() {// 启动一个协程go mytest()fmt.Println(hello, world)time.Sleep(time.Second)
}
输出结果对比如下
[rootwork day01]# go run main.go
hello, world
[rootwork day01]# go run main.go
hello, world
[rootwork day01]# go run main.go
hello, world
hello, go
[rootwork day01]# 三、WaitGroup
在上面的例子部分为了保证 main goroutine 在所有的 goroutine 都执行完毕后再退出我使用了 time.Sleep 这种简单的方式。这种方式在demo程序是可以接受的。但是当实际开发过程中不同场景下Sleep 多少时间呢是无法预测的。 因此Sleep这种方式还是尽量不要用了下面介绍下sync包提供的WaitGroup类型。
WaitGroup 案例一
代码如下示例
package mainimport (fmtsync
)func printNumbers(wg *sync.WaitGroup) {defer wg.Done() // 当某个子协程完成后可调用此方法会从计数器上减一通常可以使用 defer 来调用。for i : 1; i 5; i {fmt.Printf(%d , i)}
}func printLetters(wg *sync.WaitGroup) {defer wg.Done() // 当某个子协程完成后可调用此方法会从计数器上减一通常可以使用 defer 来调用。for char : a; char e; char {fmt.Printf(%c , char)}
}func main() {var wg sync.WaitGroup wg.Add(2) // 初始值为0你传入的值会往计数器上加这里直接传入你子协程的数量go printNumbers(wg)go printLetters(wg)wg.Wait() // 阻塞当前协程直到实例里的计数器归零。
}
结果如下
[rootwork day01]# go run main2.go
a b c d e 1 2 3 4 5WaitGroup 案例二
package mainimport (fmtio/ioutilnet/httpsync
)func fetch(url string, wg *sync.WaitGroup) {defer wg.Done()response, err : http.Get(url)if err ! nil {fmt.Printf(Error fetching %s: %v\n, url, err)return}defer response.Body.Close()body, err : ioutil.ReadAll(response.Body)if err ! nil {fmt.Printf(Error reading response body from %s: %v\n, url, err)return}fmt.Printf(Length of %s: %d\n, url, len(body))
}func main() {var wg sync.WaitGroupurls : []string{https://www.baidu.com, https://cloud.tencent.com/, https://www.qq.com/}for _, url : range urls {wg.Add(1)go fetch(url, wg)}wg.Wait()
}输出结果如下
[rootwork day01]# go run main3.go
Length of https://www.qq.com/: 328
Length of https://www.baidu.com: 2443
Length of https://cloud.tencent.com/: 235026总结
本节内容介绍了Goroutine的使用为了保证 main goroutine 在所有的 goroutine 都执行完毕后再退出我们又学习了WaitGroup。目前呢因为我们没有任何的数据交换仅仅是开启协程执行并发的任务因此没有用到信道。后面遇到复杂一些并发场景我们的goroutine通信就要用到信道的概念。这里我们下一节介绍。