1. 普通 goroutine 示例
此部分展示了如何在主函数中启动一个子协程,并说明了如何查询与设置逻辑处理器(P)的数量(代码中被注释掉)。
go
// 普通 goroutine 示例
package main
import (
"fmt"
"time"
// "runtime" // 如果需要查询或设置 GOMAXPROCS,可引入 runtime 包
)
func hello() {
fmt.Println("hello goroutine")
}
func main() {
fmt.Println("hello world!")
// GOMAXPROCS 示例:
// 查询当前设置的 P 数量(传入 0)
// fmt.Println(runtime.GOMAXPROCS(0))
// 设置 P 数量为 8
// fmt.Println(runtime.GOMAXPROCS(8))
// 再次查询当前设置的 P 数量
// fmt.Println(runtime.GOMAXPROCS(0))
// 启动一个子协程执行 hello 函数
go hello()
// 主协程休眠 1 秒,保证子协程有机会输出
time.Sleep(1 * time.Second)
}
知识点说明
- goroutine 创建 :使用
go
关键字调用函数hello()
来创建一个新的协程。 - GOMAXPROCS :可以通过
runtime.GOMAXPROCS
来查询或设置程序并发运行的 P 数量,默认为 CPU 核心数(此处代码示例中以注释形式展示)。
2. 匿名 goroutine 示例
使用匿名函数直接创建 goroutine,展示子协程与主协程同时执行的情况。
go
// 匿名 goroutine 示例
package main
import (
"fmt"
"time"
)
func main() {
// 启动一个匿名 goroutine,不断打印子协程的计数,每秒一次
go func() {
i := 0
for {
i++
fmt.Println("子协程 i =", i)
time.Sleep(1 * time.Second)
}
}()
// 主协程循环 3 次打印自己的计数,每次间隔 1 秒
for i := 0; i < 3; i++ {
fmt.Println("主协程 i =", i)
time.Sleep(1 * time.Second)
}
}
知识点说明
- 匿名 goroutine :直接在
go
后面写匿名函数,适用于简单逻辑或无需复用的协程代码。 - 并发执行:子协程与主协程各自独立运行,主协程通过循环和休眠展示执行过程。
3. 协程异常处理 ------ except_test
通过 defer
与 recover()
捕获异常,防止单个协程 panic 导致整个程序退出。
go
// 协程异常处理示例1:捕获 panic
package main
import (
"fmt"
)
func except_test() {
// 使用 defer + recover 捕获 panic
defer func() {
if r := recover(); r != nil {
fmt.Println("程序发生异常!", r)
}
}()
fmt.Println("this is except_test")
// 故意制造数组越界异常
lst := []int{1, 2, 3}
fmt.Println(lst[3]) // 索引越界,会引发 panic
}
知识点说明
- 异常捕获机制 :在函数开始使用
defer
定义匿名函数,并调用recover()
捕获 panic,从而避免未捕获异常导致整个程序崩溃。 - 故意制造异常 :通过访问越界索引
lst[3]
来触发 panic。
4. 协程异常处理 ------ except_test2
简单示例,展示协程中执行正常任务并通过休眠模拟处理耗时任务。
go
// 协程异常处理示例2:正常执行的协程
package main
import (
"fmt"
"time"
)
func except_test2() {
fmt.Println("this is except_test2")
time.Sleep(1 * time.Second)
fmt.Println("this is except_test2 end .....")
}
知识点说明
- 正常流程:该函数仅展示普通执行流程,没有异常发生,主要用于与异常处理的协程进行对比。
5. 主函数 main
在 main
函数中同时启动两个协程,一个负责异常测试(会因数组越界引发 panic,但已被捕获),另一个执行正常任务。最后通过休眠确保子协程有足够时间运行。
go
// 主函数:启动两个协程,观察异常处理效果
package main
import (
"fmt"
"time"
)
func except_test() {
defer func() {
if r := recover(); r != nil {
fmt.Println("程序发生异常!", r)
}
}()
fmt.Println("this is except_test")
lst := []int{1, 2, 3}
fmt.Println(lst[3])
}
func except_test2() {
fmt.Println("this is except_test2")
time.Sleep(1 * time.Second)
fmt.Println("this is except_test2 end .....")
}
func main() {
fmt.Println("this is main")
// 启动两个协程
go except_test()
go except_test2()
// 主协程休眠 2 秒,确保子协程执行完成
time.Sleep(2 * time.Second)
fmt.Println("end....")
}
知识点说明
- 协程并发 :同时启动两个协程,一个处理异常(
except_test
),一个正常执行(except_test2
)。 - 主协程等待 :使用
time.Sleep(2 * time.Second)
让主协程等待,保证子协程输出可见。 - 整体流程:先打印 "this is main",然后分别运行两个协程,最终在主协程结束前打印 "end..."。