goroutine channel

 

 

 

 

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

}
View Code

 

 

 

 

 

 

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線程退出")


    
}
View Code

 

 

   

 

 

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("結束")

}
View Code

 

 

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

 

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

相關文章
相關標籤/搜索