GO語言學習筆記之協程和管道
阿新 • • 發佈:2021-11-08
一、設定程式執行的CPU數量
package main import ( "fmt" "runtime" ) func main() { //獲取當前系統CPU的數量 num:=runtime.NumCPU() //設定num-1的cpu執行程式 //runtime.GOMAXPROCS(num-1) fmt.Println(num) }
二、使用互斥鎖解決資源競爭的問題
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解決資源競爭的問題
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) }
四、遍歷管道
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 可以解決從管道取資料的阻塞問題
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 } } }