package main import ( "fmt" _ "time" "sync" ) // 需求:如今要計算 1-200 的各個數的階乘,而且把各個數的階乘放入到map中。 // 最後顯示出來。要求使用goroutine完成 // 思路 // 1. 編寫一個函數,來計算各個數的階乘,並放入到 map中. // 2. 咱們啓動的協程多個,統計的將結果放入到 map中 // 3. map 應該作出一個全局的. var ( myMap = make(map[int]int, 10) //聲明一個全局的互斥鎖 //lock 是一個全局的互斥鎖, //sync 是包: synchornized 同步 //Mutex : 是互斥 lock sync.Mutex ) //使用協程+管道 ===>??? // test 函數就是計算 n!, 讓將這個結果放入到 myMap func test(n int) { res := 1 for i := 1; i <= n; i++ { res *= i } //這裏咱們將 res 放入到myMap //加鎖 lock.Lock() myMap[n] = res //concurrent map writes? //解鎖 lock.Unlock() } func main() { // 咱們這裏開啓多個協程完成這個任務[200個] for i := 1; i <= 20; i++ { go test(i) } //休眠10秒鐘【第二個問題 】 //time.Sleep(time.Second * 5) //這裏咱們輸出結果,變量這個結果 lock.Lock() for i, v := range myMap { fmt.Printf("map[%d]=%d\n", i, v) } lock.Unlock() }
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 // //若是從channel取出數據後,能夠繼續放入 <-intChan intChan<- 98//注意點, 當咱們給管寫入數據時,不能超過其容量 //4. 看看管道的長度和cap(容量) fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 3, 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*/) }
intChan 的值=0xc000086080 intChan自己的地址=0xc000080018 channel len= 3 cap=3 num2= 211 channel len= 2 cap=3 num3= 50 num4= 98
package main import "fmt" func main() { var mapchan chan map[string]string mapchan = make(chan map[string]string,10) m1 := make(map[string]string,10) m1["name"] = "阿凡達" m1["age"] = "25" m2 := make(map[string]string,10) m2["name"] = "歐陽" m2["age"] = "28" mapchan <- m1 mapchan <- m2 fmt.Println(mapchan) }
package main import "fmt" func main() { intchan := make(chan int ,3) intchan <- 100 intchan <- 200 close(intchan) fmt.Println("11111111111") n1 := <-intchan fmt.Println(n1) //100 fmt.Println(<-intchan) //200 fmt.Println(<-intchan) //0 fmt.Println(<-intchan) //0 intchan <- 300 //panic: send on closed channel }
package main import ( "fmt" "time" ) //write Data func writeData(intChan chan int) { for i := 1; i <= 50; i++ { //放入數據 intChan<- i // fmt.Println("writeData ", i) //time.Sleep(time.Second) } close(intChan) //關閉 } //read data func readData(intChan chan int, exitChan chan bool) { for { v, ok := <-intChan if !ok { break } time.Sleep(time.Second) fmt.Printf("readData 讀到數據=%v\n", v) } //readData 讀取完數據後,即任務完成 exitChan<- true close(exitChan) } func main() { //建立兩個管道 intChan := make(chan int, 10) exitChan := make(chan bool, 1) go writeData(intChan) go readData(intChan, exitChan) //time.Sleep(time.Second * 10) for { _, ok := <-exitChan if !ok { break } } }
package main import ( "fmt" "time" ) //向 intChan放入 1-8000個數 func putNum(intChan chan int) { for i := 1; i <= 80000; i++ { intChan<- i } //關閉intChan close(intChan) } // 從 intChan取出數據,並判斷是否爲素數,若是是,就 // //放入到primeChan func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) { //使用for 循環 // var num int var flag bool // for { //time.Sleep(time.Millisecond * 10) num, ok := <-intChan //intChan 取不到.. if !ok { break } flag = true //假設是素數 //判斷num是否是素數 for i := 2; i < num; i++ { if num % i == 0 {//說明該num不是素數 flag = false break } } if flag { //將這個數就放入到primeChan primeChan<- num } } fmt.Println("有一個primeNum 協程由於取不到數據,退出") //這裏咱們還不能關閉 primeChan //向 exitChan 寫入true exitChan<- true } func main() { intChan := make(chan int , 1000) primeChan := make(chan int, 20000)//放入結果 //標識退出的管道 exitChan := make(chan bool, 8) // 4個 start := time.Now().Unix() //開啓一個協程,向 intChan放入 1-8000個數 go putNum(intChan) //開啓4個協程,從 intChan取出數據,並判斷是否爲素數,若是是,就 //放入到primeChan for i := 0; i < 8; i++ { go primeNum(intChan, primeChan, exitChan) } //這裏咱們主線程,進行處理 //直接 go func(){ for i := 0; i < 8; i++ { <-exitChan } end := time.Now().Unix() fmt.Println("使用協程耗時=", end - start) //當咱們從exitChan 取出了4個結果,就能夠放心的關閉 prprimeChan close(primeChan) }() //遍歷咱們的 primeChan ,把結果取出 for { _, ok := <-primeChan if !ok{ break } //將結果輸出 //fmt.Printf("素數=%d\n", res) } fmt.Println("main線程退出") }
package main import "fmt" func send(ch chan<- int,exitchan chan struct{}){ for i :=0 ; i<10 ;i++{ ch<- i } close(ch) var a struct{} exitchan<- a } func recv(ch <-chan int,exitchan chan struct{}){ for{ v,ok:= <-ch if !ok{ break } fmt.Println(v) } var a struct{} exitchan<- a } func main() { var ch chan int ch = make(chan int,10) exitchan := make(chan struct{},2) go send(ch,exitchan) go recv(ch,exitchan) //var total = 0 //for _ = range exitchan{ // total++ // if total ==2{ // break // } //} var total = 0 for{ _,ok:= <-exitchan if !ok{ break } total++ if total ==2{ break } } fmt.Println("結束") }
package main import "fmt" func main() { intchan := make(chan int,10) for i := 0;i<10;i++{ intchan <- i } stringchan := make(chan string ,5) for i:=0;i<5;i++{ stringchan<- "hello"+fmt.Sprintf("%d",i) } for{ select{ case v:= <-intchan: fmt.Printf("從intchan讀取的數據%d\n",v) case v := <-stringchan: fmt.Printf("從stringchan讀取的數據%d\n",v) default: fmt.Printf("都取不到了,不玩了") return } } }
package main import ( "time" "fmt" ) func sayHello(){ for i:=0;i<10;i++{ //time.Sleep(time.Second) fmt.Println("hello world") } } func test(){ defer func(){ if err := recover();err!=nil{ fmt.Println("test() 發生錯誤",err) } }() var myMap map[int]string //myMap = make(map[int]string,6) myMap[0] = "golang" } func main() { go sayHello() go test() time.Sleep(time.Second*10) }
GOROOT=D:\go #gosetup GOPATH=null #gosetup D:\go\bin\go.exe build -i -o C:\Users\Administrator\AppData\Local\Temp\___go_build_03_go.exe D:/gospace/03.go #gosetup D:\soft\GoLand\bin\runnerw.exe C:\Users\Administrator\AppData\Local\Temp\___go_build_03_go.exe #gosetup hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world test() 發生錯誤 assignment to entry in nil map
sync:golang
sync案例ide
上圖每次執行結果都不相同函數
經過加互斥鎖ui