GO语言学习笔记之协程和管道
一、设置程序运行的CPU数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import ( "fmt" "runtime" ) func main() { //获取当前系统CPU的数量 num:=runtime.NumCPU() //设置num-1的cpu运行程序 //runtime.GOMAXPROCS(num-1) fmt.Println(num) } |
二、使用互斥锁解决资源竞争的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package main import ( "fmt" "sync" "time" ) var ( mp =make( map [int]int,10) lock sync.Mutex ) func test(n int){ lock.Lock() mp[n]=n lock.Unlock() } func main() { for i:=0;i<200;i++{ go test(i) } time.Sleep(time.Second*10) for i:=0;i<200;i++{ fmt.Println(mp[i]) } } |
三、使用管道channel解决资源竞争的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package main import ( "fmt" ) func main() { //演示一下管道的使用 //1. 创建一个可以存放 3 个 int 类型的管道 var intChan chan int intChan = make( chan int, 3) //2. 看看 intChan 是什么 fmt.Printf( "intChan 的值=%v intChan 本身的地址=%p\n" , intChan, &intChan) //3. 向管道写入数据 intChan<- 10 num := 211 intChan<- num intChan<- 50 // intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量 //4. 看看管道的长度和 cap(容量) fmt.Printf( "channel len= %v cap=%v \n" , len(intChan), cap(intChan)) // 3, //5. 从管道中读取数据 var num2 int num2 = <-intChan fmt.Println( "num2=" , num2) fmt.Printf( "channel len= %v cap=%v \n" , len(intChan), cap(intChan)) // 2, 3 //6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock //num3 := <-intChan //num4 := <-intChan //num5 := <-intChan //fmt.Println("num3=", num3, "num4=", num4, "num5=", num5) } |
四、遍历管道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package main import "fmt" func main() { var arr chan int arr=make( chan int,100) for i:=1;i<101;i++{ arr<-i*5 } close(arr) //遍历管道必须关闭,否则会报错deadlock for v:= range arr{ fmt.Println(v) } } |
五、channel使用注意事项和细节
1) channel 可以声明为只读,或者只写性质
2)使用 select 可以解决从管道取数据的阻塞问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | package main import ( "fmt" "time" ) func main() { //使用 select 可以解决从管道取数据的阻塞问题 //1.定义一个管道 10 个数据 int intChan := make( chan int, 10) for i := 0; i < 10; i++ { intChan <- i } //2.定义一个管道 5 个数据 string stringChan := make( chan string, 5) for i := 0; i < 5; i++ { stringChan <- "hello" + fmt.Sprintf( "%d" , i) } //传统的方法在遍历管道时,如果不关闭会阻塞而导致 deadlock //问题,在实际开发中,可能我们不好确定什么关闭该管道. //可以使用 select 方式可以解决 //label: for { select { //注意: 这里,如果 intChan 一直没有关闭,不会一直阻塞而 deadlock //,会自动到下一个 case 匹配 case v := <-intChan: fmt.Printf( "从 intChan 读取的数据%d\n" , v) time.Sleep(time.Second) case v := <-stringChan: fmt.Printf( "从 stringChan 读取的数据%s\n" , v) time.Sleep(time.Second) default : fmt.Printf( "都取不到了,不玩了, 程序员可以加入逻辑\n" ) time.Sleep(time.Second) return //break label } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码