• GO channel


    理念

    GO语言并发模型CSP: 提倡通过通信共享内存,而非通过共享内存实现通信

    如果说goroutine是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制

    示例

    关闭后任然可以读取

    func main() {
        ch := make(chan int, 2)
        ch <- 1
        ch <- 2
        close(ch)
        a, ok1 := <-ch
        b, ok2 := <-ch
        c, ok3 := <-ch
        fmt.Println(a, ok1)
        fmt.Println(b, ok2)
        fmt.Println(c, ok3)
    }

    执行:

    1 true
    2 true
    0 false

    异常示例

    # 无缓冲通道导致异常

    import "fmt"
    
    func baseTest() {
        ch := make(chan int)
        ch <- 10
        fmt.Println("发送成功")
    }
    
    func main() {
        baseTest()
    }

    执行:fatal error: all goroutines are asleep - deadlock!

    原因:ch := make(chan int) 创建的是无缓冲通道,只有在有地接收值时才会发送成功。

    # 通道无空间,继续读取

    func testClose() {
        ch := make(chan int, 2)
        ch <- 1
        ch <- 2
        //close(ch)
        a, ok1 := <-ch
        b, ok2 := <-ch
        c, ok3 := <-ch
        fmt.Println(a, ok1)
        fmt.Println(b, ok2)
        fmt.Println(c, ok3)
    }

    执行:fatal error: all goroutines are asleep - deadlock!

    # 关闭后,任往通道发送

    func main() {
        ch := make(chan int, 2)
        ch <- 1
        close(ch)
        ch <- 2
        a, ok1 := <-ch
        b, ok2 := <-ch
        c, ok3 := <-ch
        fmt.Println(a, ok1)
        fmt.Println(b, ok2)
        fmt.Println(c, ok3)
    }

    执行:

    panic: send on closed channel

    #解1:无缓冲通道

    import "fmt"
    
    func recv(ch chan int) {
        ret := <- ch
        fmt.Println("接收成功: ", ret)
    }
    
    func unBuffer() {
        ch := make(chan int)
        go recv(ch)
        ch <- 10
        fmt.Println("发送成功")
    }
    
    func main() {
        unBuffer()
    }

    执行:

    接收成功: 10
    发送成功

    #解2:有缓冲通道

    import "fmt"
    
    func buffer() {
        ch := make(chan int, 2)
        ch <- 10
        fmt.Println("发送成功")
    }
    func main() {
        buffer()
    }

    执行:

    发送成功

    问题:当发送到chan大于其长度,并且没有消费时,造成死锁

    import "fmt"
    
    func buffer() {
        ch := make(chan int, 2)
        ch <- 10
        ch <- 11
        ch <- 12
        fmt.Println("发送成功")
    }
    func main() {
        buffer()
    }

    执行:

    fatal error: all goroutines are asleep - deadlock! 

    综合示例

    读取对通道a中的数字,在通道b中平方

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    var wg2 sync.WaitGroup
    
    func f1(ch1 chan int) {
        defer wg2.Done()
        for i := 0; i < 100; i++ {
            ch1 <- i
        }
        close(ch1)
    }
    
    func f2(ch1, ch2 chan int) {
        defer wg2.Done()
        for {
            x, ok := <-ch1
            if !ok {
                break
            }
            ch2 <- x * x
        }
        close(ch2)
    }
    
    func testClose() {
        ch := make(chan int, 2)
        ch <- 1
        ch <- 2
        close(ch)
        a, ok1 := <-ch
        b, ok2 := <-ch
        c, ok3 := <-ch
        fmt.Println(a, ok1)
        fmt.Println(b, ok2)
        fmt.Println(c, ok3)
    }
    
    func main() {
        //testClose()
        a := make(chan int, 100)
        b := make(chan int, 100)
        wg2.Add(2)
        go f1(a)
        go f2(a, b)
        wg2.Wait()
        for x := range b {
            fmt.Println(x)
        }
    }

    执行:

    0
    1
    4
    9
    16

    ...

    单向通道

    <-chan:只做输出的通道

    chan<-:只做输入的通道

    示例: 重写上面例子中f2

    func f2Uni(ch1 <-chan int, ch2 chan<- int) {
        defer wg2.Done()
        for {
            x, ok := <-ch1
            if !ok {
                break
            }
            ch2 <- x * x
        }
        close(ch2)
    }
  • 相关阅读:
    Laravel schema构建器列类型
    wkhtmltopdf docker + java(环境搭建及一些坑)
    dockerfile,仓库,私有仓库流程(转载)
    wkhtmltopdf参数详解及精讲使用方法(转载)
    传统前端项目中进行模块化编程并引入使用vue、elementui 前端
    vue3 + vuex4 实践 前端
    elementplus 原生开发 日期国际化语言 前端
    Vite2.0打包elementplus UI报错 前端
    vue3 Vetur报错:has no default export 组件没导出 前端
    windows版的HbuilderX连接iPad真机测试(uniapp)
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/15863621.html
Copyright © 2020-2023  润新知