通道

作者: isuntong | 来源:发表于2020-03-25 21:54 被阅读0次

channel通道

package main

import "fmt"

//15
func main() {
    /*
    channel
    */

    var a chan int
    fmt.Printf("%T,%v\n",a,a) //chan int,<nil>

    if a == nil {
        fmt.Println("channel是nil的,不能使用,需要先创建通道")
        a = make(chan int)
        fmt.Println(a) //0xc00008c060
    }

    test1(a)

    var ch1 chan bool
    ch1 = make(chan bool)

    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println("子goroutine:",i)
        }
        //循环结束,向通道中写数据
        ch1 <- true
        fmt.Println("结束。。。") //结束。。。
    }()

    //写之前读阻塞,读之前写阻塞
    data := <- ch1
    fmt.Println("main data --->",data) //main data ---> true
    fmt.Println("main over") //main over
}

func test1(ch chan int){
    fmt.Printf("%T,%v\n",ch,ch) //chan int,0xc000100060
}

关闭通道和通道上范围循环

package main

import (
    "fmt"
    "time"
)

//16
func main() {
    /*
    关闭通道:close(ch)
        子groutine,写出10个数据
            每写一个,阻塞一次,主goroutine读取一次,解除阻塞

        主goroutine,读取数据
            每次读取数据,阻塞一次,子goroutine,写出一个,解除阻塞

    */
    ch1 := make(chan int)
    go sendData(ch1)

    //读取通道的数据
    for{
        time.Sleep(1 * time.Second)
        v,ok := <- ch1
        if !ok {
            fmt.Println("已经读取了所有数据",v,ok)
            break
        }
        fmt.Println("读取的数据:",v,ok)
    }
    fmt.Println("main over")

}

func sendData(ch1 chan int)  {
    //发送方
    for i := 0; i < 10; i++ {
        ch1 <- i
    }
    close(ch1)
}

package main

import (
    "fmt"
)

//17
func main() {
    /*
    通过range访问通道
    */
    ch1 := make(chan int)
    go sendData2(ch1)

    //range来访问通道
    for v := range ch1 {
        fmt.Println("读取数据:",v)
    }
    fmt.Println("main over")

}

func sendData2(ch1 chan int)  {
    //发送方
    for i := 0; i < 10; i++ {
        ch1 <- i
    }
    close(ch1) //通知对方通道关闭
}

缓冲通道

package main

import (
    "fmt"
    "strconv"
)

//18
func main() {
    /*
        非缓冲通道:make(chan T)
            一次发送,一次接受,都是阻塞的
        缓冲通道:make(chan T,capacity)
            发送:缓冲区的数据满了,才会阻塞
            接收:缓冲区的数据空了,才会阻塞
    */
    ch1 := make(chan int)
    fmt.Println(len(ch1), cap(ch1)) //0 0

    ch2 := make(chan int, 5)
    fmt.Println(len(ch2), cap(ch2)) //0 5

    ch2 <- 100
    fmt.Println(len(ch2), cap(ch2)) //1 5

    ch2 <- 100
    ch2 <- 200
    ch2 <- 300
    ch2 <- 400
    fmt.Println(len(ch2), cap(ch2)) //5 5

    // ch2 <- 600 //fatal error: all goroutines are asleep - deadlock!

    fmt.Println("-------------")
    ch3 := make(chan string, 4)
    go sendData3(ch3)

    for{
        v,ok := <-ch3
        if !ok {
            fmt.Println("读完了..",ok)
            break
        }
        fmt.Println("\t读取的数据是:",v)
    }
    fmt.Println("main over...")

}

func sendData3(ch chan string){
    for i := 0; i < 10; i++ {
        ch <- "数据" + strconv.Itoa(i)
        fmt.Println("子goroutine中写出第 %d 个数据\n",i)
    }
    close(ch)
}

定向通道

package main

import "fmt"

//19
func main() {
    /*
        双向通道
            chan T
                chan <- data,发送数据,写出
                data <- chan,获取数据,读取

        单向:定向
            chan <- T,只支持写操作
            <- chan T,只读
    */
    ch1 := make(chan string)
    done := make(chan bool)
    go sendData4(ch1, done)

    data := <- ch1
    fmt.Println("子goroutine传来:",data) //子goroutine传来: isuntong

    ch1 <- "isuntong2"

    <- done //不通知不要结束
    fmt.Println("main over...")

}

func sendData4(ch1 chan string, done chan bool) {
    ch1 <- "isuntong"

    data := <- ch1
    fmt.Println("main goroutine传来:",data)

    done <- true
}

package main

import "fmt"

//20
func main() {
    /*
        单向:定向
            chan <- T,只支持写操作
            <- chan T,只读

    用作默写函数保护
    函数内部对于ch1只能读,不能写,所以可以保护安全

    创建双向channel,在某些函数中限定只读只写,作为保护。

    */
    ch1 := make(chan int) //双向,读写
    //ch2 := make(chan <- int) //单向,只能写
    //ch3 := make(<- chan int) //单向,只能读

    // ch2 <- 1000
    // data := <-ch2 //invalid operation: <-ch2 (receive from send-only type chan<- int)

    // data := <- ch3
    // ch3 <- 2000 //invalid operation: ch3 <- 2000 (send to receive-only type <-chan int)
    // fmt.Println(data)

    go fun3(ch1) //可读可写
    // fun3(ch2)

    data2 := <- ch1
    fmt.Println("fun3函数写出的数据是:",data2) //fun3函数写出的数据是: 100

}

//该函数,只能操作只写的通道
func fun3(ch chan <- int) {
    ch <- 100
    fmt.Println("fun3函数结束") //fun3函数结束
}

func fun4(ch <- chan int) {

    fmt.Println("fun3函数结束") //fun3函数结束
}

time包中的通道相关函数

package main

import (
    "fmt"
    "time"
)

//21
func main() {
    /*
        1. func NewTimer(d Duration) *Timer
            创建一个计数器,d时间以后触发

        2. func After(d Duration) <- chan Time
            返回一个通道,存储的是d时间间隔之后的当前时间

    */
    timer := time.NewTimer(3 * time.Second)
    fmt.Printf("%T\n",timer) //*time.Timer
    fmt.Println(time.Now()) //2020-03-26 19:29:30.612334 +0800 CST m=+0.000112607

    //此处等待channel中的数据,会阻塞3秒
    ch2 := timer.C
    fmt.Println(<-ch2) //2020-03-26 19:29:33.614302 +0800 CST m=+3.002032115

    //新建一个计数器
    timer2 := time.NewTimer(5 * time.Second)
    //开始goroutine,来处理触发后的事件
    go func() {
        <- timer2.C
        fmt.Println("Timer2结束")
    }()

    time.Sleep(3 * time.Second)
    flag := timer2.Stop() //停止定时
    if flag {
        fmt.Println("Timer2停止了")
    }


    //After(d Duration)
    ch := time.After(3 * time.Second)
    fmt.Printf("%T\n",ch) //<-chan time.Time
    fmt.Println(time.Now()) //2020-03-26 19:40:21.089133 +0800 CST m=+6.004003279

    timer3 := <-ch
    fmt.Println(timer3) //2020-03-26 19:40:24.091121 +0800 CST m=+9.005942476

}

select语句

package main

import (
    "fmt"
    "time"
)

//22
func main() {
    /*
    分支语句:if、switch、select
    select类似于switch语句
        但是select语句会随机执行一个可运行的case
        如果没有case可以执行,要看是否有default,如果有就执行default,否则就进入阻塞,直到有case可以运行


     */

    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() {
        time.Sleep(3 * time.Second)
        ch1 <- 100
    }()

    go func() {
        time.Sleep(3 * time.Second)
        ch2 <- 200
    }()

    select {
    case num1 := <- ch1:
        fmt.Println("ch1中获得数据是:", num1)
    case num2,ok := <-ch2:
        if ok{
            fmt.Println("ch2中获得的数据是:",num2)
        }else {
            fmt.Println("ch2通道已关闭")
        }
    default:
        fmt.Println("default语句。。。")

    }

    fmt.Println("main over...")

}

CSP并发模型

相关文章

  • 通道的运用

    复合通道,颜色通道,专色通道,记录选区阿尔法通道,

  • 通道

    channel通道 关闭通道和通道上范围循环 缓冲通道 定向通道 time包中的通道相关函数 select语句 C...

  • 梦通道,行通道

    09年的诗呢 那时还真有心情 哪怕现在晃荡如我 也是再也没有当时的心情呢 当时那文艺的 文艺女青年是个贬义词,现在...

  • <>

    通道的高级玩法 单向通道 单向通道是只允许写或者读的通道,定义方式如下: 通道的读写 for语句读写 select...

  • 知识人脉积累好,管理也可转专业-171-90-34-1473

    【实操技巧:双通道职业发展通道中,管理怎么转专业? 我们公司有个职业双通道路径,管理通道与专业通道是...

  • Photoshop百种技巧六

    81. 使用通道处理图片中的天空 A: 复制蓝色通道 去通道工具窗口拖动蓝色通道到创建新通道的按钮上,复制它。点击...

  • 通道

    2月11号,也就是今天,我们早上起来后,大概九点左右,我们出发了! 坐上了车,开始了今天的路程,我...

  • 通道

    文/湘邵铁炉 晚上好【今日铁炉说——通道】:今天我所说的这个通道是通往成功的通道,话说“七十...

  • 通道

    又一次走过渐渐熟悉的通道。 傻子,傻子,傻子!要不要走个通道都这么伤感! 到站了,有人下了,我也应该下,可是,我没...

  • 通道

    通道的应用: 创建不可能的选区和蒙版 确定对象和背景——复制反差最强的通道副本——将对象变黑背景变白(色阶吸管、填...

网友评论

      本文标题:通道

      本文链接:https://www.haomeiwen.com/subject/qguxuhtx.html