协程非常简单,直接函数前加一个go就可以了
阻塞运行 #
package main
func task() {
for {
println("task func")
}
}
func main() {
task()
println("main over")
}
执行结果一直运行输出:
task func
task func
....
开启一个协程 #
package main
func task() {
for {
println("task func")
}
}
func main() {
go task()
println("main over")
}
输出内容:
main over
这个输出内容不确定,如果开启协程速度快于main,会输出
main over
task func
出现上面的问题是因为主程序退出,启动的协程也自动关闭
设置主程序的执行时间 #
主程序设置
func task() {
for {
println("task func")
}
}
func main() {
//debug()
go task()
time.Sleep(time.Millisecond * 2) //延迟2毫秒后继续运行
println("main over")
}
输出内容
task func
task func
...
main over
task func //有的时候会出现,主要是看主程序执行完成,回收goroutine的时间点
如果想最后输出一定要main over可以通过defer关键字
func main() {
//debug()
go task()
//延迟2毫秒后继续运行
time.Sleep(time.Millisecond * 2)
//or 通过接收2毫秒延迟channel通知 同上
<-time.After(time.Millisecond * 2)
defer println("main over")
//多个延迟执行可以 defer延迟执行,释放资源,关闭文件,关闭连接,关闭channel等
//defer println("main over 1")
//defer println("main over 2")
//也可以通过封装一个匿名函数中
//defer func() {
// println("main over")
//}()
}
- 通过defer 延迟执行
- defer 可以写多行
- defer 可以运行匿名函数,函数内写释放资源的代码
主程序一直执行 #
func main() {
//debug()
go task()
time.Sleep(time.Millisecond * 2) //延迟2毫秒
defer println("main over")
//阻塞的死循环
for {
}
//或通过select接收或发送channel进行阻塞 同上
select {
}
//或者通过中断信号接收后停止运行
sig := make(chan os.Signal)
signals := []os.Signal{syscall.SIGINT,syscall.SIGQUIT}
signal.Notify(sig,signals...)
//同上 SIGINT发送INTR字符(Ctrl+C)触发 SIGQUIT发送QUIT字符(Ctrl+/)触发
//signal.Notify(sig,syscall.SIGQUIT,syscall.SIGINT)
<-sig
//同上
//select {
//case <-sig:
//
//}
}
- 方法1 通过for死循环
- 通过select case接收和发送信道
- 通过用户发送信号
子协程和主程序通信 #
func task() {
i := 0
for {
i++
println("task func",i)
if i == 200 {
quit <- true
break //如果不加break,在主程序接收quit通知时i会继续打印201 202 ...
}
}
close(quit)
}
var quit = make(chan bool)
func main() {
go task()
<- quit
defer println("main over")
}
改造上面程序,通过形参的方式传递channel
-
goroutine中处理业务,处理中断出,发送quit的通知channel
-
主程序阻塞等待 <- quit,接收到信息后继续下面执行
//发送通知
func task(q chan <- bool) {
i := 0
for {
i++
println("task func",i)
if i == 200 {
q <- true //发送退出通知
break
}
}
}
func main() {
quit := make(chan bool)
go task(quit)
<- quit //等待接收
defer println("main over")
}
channel不是全局变量而是局部变量,可以通过形参的形式传递
信道的发送和接收 #
//通过发送
func send(ch chan <- int) {
i := 0
for {
i++
println("task func",i)
ch <- i
}
defer close(ch) //能关闭发送channel
}
//接收
func receive(ch <-chan int) {
for c := range ch {
println(c)
}
}
func main() {
ch := make(chan int)
go send(ch)
go receive(ch)
time.Sleep(time.Millisecond * 5)
defer func() {
println("main over")
}()
}
如果传递参数未标明是接收信道还是发送信道,就可以在接收channel中进行lclose
func send(ch chan int) {
i := 0
for {
i++
println("task func", i)
ch <- i
}
}
func receive(ch chan int) {
for c := range ch {
println(c)
}
defer close(ch)
}