golang中channel的用法

栏目: Go · 发布时间: 6年前

内容简介:以下是

channel 有点类似于管道,它在 goroutine 同步与通信中,有着起承转合的作用,同时也是 Golang 实现 CSP 模型的关键

package main

func main() {
    senderOnly := make(chan<- int)   // 只能用来发送(管道的入口,只进不出)
    receiverOnly := make(<-chan int) // 只能用来接收(管道的出口,只出不进)
    unbuffer := make(chan int)       // 无缓冲可收发
    buffer := make(chan int, 2)      // 无缓冲可收发
    println(senderOnly, receiverOnly, unbuffer, buffer)
}

以下是 channel 的一些使用场景

等待goroutine完成

package main

func main() {
    println("start main")
    ch := make(chan bool)
    go func() {
        println("come into goroutine")
        ch <- true
    }()

    println("do something else")
    <-ch
    close(ch)

    println("end main")
}

在playground中运行

打印结果:

start main
do something else
come into goroutine
end main

多个goroutine协同

三个功能不相关的 goroutine 最后结果要汇总累加到 result

package main

func main() {
    println("start main")
    ch := make(chan int)

    var result int
    go func() {
        println("come into goroutine1")
        var r int
        for i := 1; i <= 10; i++ {
            r += i
        }
        ch <- r
    }()

    go func() {
        println("come into goroutine2")
        var r int = 1
        for i := 1; i <= 10; i++ {
            r *= i
        }
        ch <- r
    }()

    go func() {
        println("come into goroutine3")
        ch <- 11
    }()

    for i := 0; i < 3; i++ {
        result += <-ch
    }
    close(ch)
    println("result is:", result)
    println("end main")
}

在playground中运行

其中一组打印结果:

start main
come into goroutine3
come into goroutine2
come into goroutine1
result is: 3628866
end main

Select

两个 goroutine 无直接关联,但其中一个先达到某一设定条件便退出或超时退出

package main

import "time"

func main() {
    println("start main")
    cond1 := make(chan int)
    cond2 := make(chan uint64)

    go func() {
        for i := 0; ; i++ {
            cond1 <- i
        }
    }()

    go func() {
        var i uint64
        for ; ; i++ {
            cond2 <- i
        }
    }()

    endCond := false
    for endCond != true {
        select {
        case a := <-cond1:
            if a > 99 {
                println("end with cond1")
                endCond = true
            }
        case b := <-cond2:
            if b == 100 {
                println("end with cond2")
                endCond = true
            }
        case <-time.After(time.Microsecond):
            println("end with timeout")
            endCond = true
        }
    }

    println("end main")
}

在playground中运行

其中打印结果有可能是:

start main
end with cond1
end main

也有可能是:

start main
end with timeout
end main

也可能是:

start main
end with cond2
end main

这说明循环100次大概需要1微秒的时间

channel与range

package main

import "fmt"

func main() {
    println("start main")
    ch := make(chan int, 4)
    go func() {
        for i := 0; i < 10; i++ {
            ch <- i
        }
        // 如果不关闭channel,会引发panic
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
    println("end main")
}

打印结果为:

start main
0
1
2
3
4
5
6
7
8
9
end main

无缓冲 channel

package main

func main() {
    var ch = make(chan int)
    ch <- 1
    println(<-ch)
}

在playground中运行

打印结果为:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /tmp/sandbox117018544/main.go:5 +0x60

死锁了,为什么会这样呢,因为 ch 是一个无缓冲的 channel ,在执行到 ch <- 1 就阻塞了当前 goroutine (也就是main函数所在的 goroutine ),后面打印语句根本没机会执行

稍加修改即能正常运行

在playground中运行
package main

func main() {
    var ch = make(chan int)
    go func() {
        ch <- 1
        println("sender")
    }()
    println(<-ch)
}

因为此时 ch 既有发送也有接收而且不在同一个 goroutine 里面,此时它们不会相互阻塞


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

SEO实战密码

SEO实战密码

昝辉Zac / 电子工业出版社 / 2015-7 / 69.00元

本书是畅销书升级版,详细和系统地介绍了正规、有效的SEO实战技术,包括为什么要做SEO、搜索引擎工作原理、关键词研究、网站结构优化、外部链接建设、SEO效果监测及策略修改,SEO作弊及惩罚、排名因素列表、常用的SEO工具、SEO项目管理中需要注意的问题等专题,最后提供了一个非常详细的案例供读者参考。 第3版增加了移动搜索优化、APP排名优化、百度2015年排名因素调查结果等新内容,并对前两版......一起来看看 《SEO实战密码》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具