设为首页 加入收藏

TOP

goroutine(二)
2019-02-21 12:08:07 】 浏览:313
Tags:goroutine
aitgroup wg.Add(1) go say("Hey") //添加一个 goroutine 到 waitgroup wg.Add(1) go say("There") // 告诉程序等待以上添加到 waitGroup 的 goroutine 运行结束再向下执行 wg.Wait() -----以上可以看作是以wg.Wait()为分割的第一个 waitGroup, 以下为第二个---- //添加一个 goroutine 到另一个 waitgroup wg.Add(1) go say("Hi") // 告诉程序等待这个 waitGroup 里的 goroutine 运行结束再向下执行 wg.Wait() }

输出结果如下

There
Hey
There
Hey
There
Hey
Hi
Hi
Hi

4. Defer

defer statement will defer running the function until the end of the surrounding function, either that the function is done, or if the function does happened error panic out, the defer statement will run.
defer 遵循先进后出原则, 所以是倒叙执行
在上面的例子中, 我们看到 wg.Done() 函数是写在 for 循环后面的, 那么如果前面执行中如果出了错误, 程序就永远无法执行到 wg.Done() 函数, 那么整个程序就会无限制地等下去, 对于这个问题, 我们可以把 wg.Done() 函数写在 defer 语句后面, 而且放在函数的最前面,这样不管后面的执行是正常返回, 还是报错, 都会最终执行到 wg.Done() 函数. 这样才能正常向下执行.

func say(s string) { // defer 语句会确保函数 wg.Done() 执行,且是在函数内其他程序之后 defer wg.Done() // 告知所有的 goroutine 运行结束, 程序可以返回 for i := 0; i<3; i++ { fmt.Println(s) time.Sleep(time.Millisecond*100) } } 

5. panic 和 recover

func cleanUp() { defer wg.Done() if r := recover(); r != nil { fmt.Println("Recover from cleanUp:", r) } } func say(s string) { defer cleanUp() for i := 0; i<3; i++ { fmt.Println(s) time.Sleep(time.Millisecond*100) if i == 1 { panic("oh my god") } } } func main() { //添加一个 goroutine 到 waitgroup wg.Add(1) go say("Hey") //添加一个 goroutine 到 waitgroup wg.Add(1) go say("There") // 告诉程序等待 goroutine 运行 wg.Wait() fmt.Println("this is something") //添加一个 goroutine 到 waitgroup wg.Add(1) go say("Hi") // 告诉程序等待 goroutine 运行 wg.Wait() } 

运行结果, 可以看到由于在 i=1 的时候, 运行 panic()函数, 所以只能循环两次, for 循环遇到 panic 就会停止执行, 然后运行被 defer 的 cleanUp()函数, 在这个函数里, 调用了 recover()函数, 调用 recover 函数, 就会得到 panic()函数的返回值, 我们将此值赋值给了变量 r, 当 r 不等于 nil 的时候, 打印它. 最后再执行被 defer 的 wg.Done() 函数, 告知程序向下执行.

There
Hey
There
Hey
Recover from cleanUp: oh my god
Recover from cleanUp: oh my god
this is something
Hi
Hi
Recover from cleanUp: oh my god

6. Channel

package main import ( "fmt" "sync" ) var wg sync.WaitGroup // 用于向通道里传值的函数 func foo(c chan int, val int) { wg.Done() //把接收到的值乘以5后传给指定的通道 c <- val * 5 } func main() { // 创建一个通道, buffer 为10, 也就是可以缓冲 10个值 fooVal := make(chan int, 10) //循环10次调用 foo()函数, 也就是向 fooVal 通道里传了10个值 for i := 1; i < 10; i++ { wg.Add(1) go foo(fooVal, i) } //等待向通道传值的 goroutine 全部完成 wg.Wait() // 通道用完, 需要及时关闭 close(fooVal) // 把通道里的值循环打印出来 for item := range fooVal { fmt.Println(item) } }
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇[Go] golang的select多路选择功能 下一篇使用Golang搭建web服务

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目