• channel用法和源码


    源码分析https://mp.weixin.qq.com/s/eCwZMwGjU2yoXu6K2nGF3g

    1 当chan用close关闭时,无论是有缓存的还是无缓存的,返回已缓冲数据或零值,如果重复用close关闭chan或对关闭的chan写入值都会报错,

    https://blog.csdn.net/qq_41065919/article/details/107729571

    https://www.cnblogs.com/pluse/p/12167537.html

    struct{}类型好像只有一种具体实例即struct{}{},chan中如果有这种类型,只能写入它的零值struct{}{},所以类型为struct{}的chan无论是写入还是读出都时零值,

    func main()  {
        m := make(chan struct{}, 1)
        // 从空的m中一直读取值会一直阻塞,所以会报死锁的错误,all goroutines are asleep - deadlock!
        //b := <- m
        //fmt.Println(b)
        // 如果这里就关闭了协程,下面会直接输出chan中的零值,而不会走default,
        //close(m)
        //m <- struct{}{}
        go func() {
            for{
                select {
                case a := <- m:
                    fmt.Println(a)
                    time.Sleep(time.Second)
                default:
                    fmt.Println("chan为空,读取的时候会阻塞")
                    time.Sleep(time.Second)
                }
            }
        }()
        // 加这个是为了主协程等待里面的子协程,否则的话主协程直接执行完了,观察不到子协程的具体输出,
        time.Sleep(time.Second * 5)
    }
    View Code

    a 如果close无缓存channel,

    1> close前没有因为写入阻塞,则读出的是channe里类型的零值,

    2> 如果写入阻塞了,则第一次读出的是写入的值,之后读出的是零值,

    func main()  {
        m := make(chan int)
        go func() {
            m <- 555
            // 这里虽然close了,但之后第一次读出的仍是第一次写入的值,
            close(m)
            // 保证close在读之前
            time.Sleep(time.Second * 3)
        }()
        go func() {
            for{
                select {
                case a := <- m:
                    if a != 0{
                        fmt.Println("第一次从channel中读出的值为colse前写入的值", a)
                    } else{
                        fmt.Println("之后读出的值为int类型的零值", a)
                    }
                    time.Sleep(time.Second)
                default:
                    fmt.Println("chan为空,读取的时候会阻塞")
                    time.Sleep(time.Second)
                }
            }
        }()
        time.Sleep(time.Second * 4)
    }
    View Code

    b 如果close有缓存channel,

    1> close前没有写入,则读出的是channel里类型的零值,

    2> 如果close前写入了,则会按队列的顺序把数据依次取出来,

    func main()  {
        m := make(chan int, 3)
        m <- 111
        m <- 222
        close(m)
        go func() {
            for{
                select {
                case a := <- m:
                    if a != 0{
                        fmt.Println("读出的值是之前写入的值", a)
                    } else{
                        fmt.Println("之后读出的值为int类型的零值", a)
                    }
                    time.Sleep(time.Second)
                default:
                    fmt.Println("chan为空,读取的时候会阻塞")
                    time.Sleep(time.Second)
                }
            }
        }()
        time.Sleep(time.Second * 4)
    }
    View Code

    待学习:https://i6448038.github.io/2019/04/11/go-channel/

  • 相关阅读:
    Mysql
    JavaScript常用事件
    css
    HTML
    判断pc还是手机打开跳转到别的网页
    queue 队列
    兼容firstChild和firstElementChild
    总结各种width,height,top,left
    原生js提取非行间样式
    ie8 不支持media
  • 原文地址:https://www.cnblogs.com/xxswkl/p/14218945.html
Copyright © 2020-2023  润新知