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
        }
    }
}

  

 

posted @   ☞@_@  阅读(63)  评论(0编辑  收藏  举报
编辑推荐:
· 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,欢迎大家贡献代码
点击右上角即可分享
微信分享提示