1. 程式人生 > 其它 >GO語言學習筆記之協程和管道

GO語言學習筆記之協程和管道

一、設定程式執行的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
		}
	}
}