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

相关文章
相关标签/搜索