• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

GO channel

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

理念

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

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
【区块链Go语言实现】Part 2:工作量证明机制POW发布时间:2022-07-10
下一篇:
[Go]解决importedfromimplicitlyrequiredmodule发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap