package main import ( "fmt" "time" ) func test() { for i := 0; i < 5; i++ { fmt.Printf("协程(具名函数) i = %+v \n", i) time.Sleep(time.Second) // 休眠1秒 } } func main() { // 开启协程(具名函数) go test() // 开启协程(匿名函数) go func() { for i := 0; i < 5; i++ { fmt.Printf("协程(匿名函数) i = %+v \n", i) time.Sleep(time.Second) // 休眠1秒 } }() // 主线程的for循环 for i := 0; i < 5; i++ { fmt.Printf("主线程 i = %+v \n", i) time.Sleep(time.Second) // 休眠1秒 } // ========== 输出过程·开始 ========== // // 主线程 i = 0 // 协程(匿名函数) i = 0 // 协程(具名函数) i = 0 // 协程(具名函数) i = 1 // 协程(匿名函数) i = 1 // 主线程 i = 1 // 协程(具名函数) i = 2 // 协程(匿名函数) i = 2 // 主线程 i = 2 // 主线程 i = 3 // 协程(匿名函数) i = 3 // 协程(具名函数) i = 3 // 协程(具名函数) i = 4 // 协程(匿名函数) i = 4 // 主线程 i = 4 // ========== 输出过程·结束 ========== // } // ========== 总结 ========== // // 1、Go开启协程非常简单,使用go关键字,在其后面调用具名函数或匿名函数即可。 // 2、协程是依附主线程的,即只要主线程退出了,不管协程有没有开始或执行到哪里,协程都会退出。以上面的代码为例,如果把两个协程 // 的for循环放到主线程之后,那么两个协程就都不会执行了,因为主线程执行完for循环就会退出。 // 对于协程嵌套的情况亦是如此,父协程和子协程都是依附主线程的,在主线程没退出的前提下,父协程执行完并不会中断子协程的执行。 // 3、协程的调度永远是不可预测的,即在设置了多个协程的情况下,开发者永远不知道哪个协程会先执行,即便是代码里出现了诸如 // runtime.GOMAXPROCS(1)、runtime.Gosched()等语句,这些函数的作用仅仅只是让协程的切换变得频繁,并不会让协程的调度变得可预测。
Copyright © 2025 码农人生. All Rights Reserved