下载APP
登录
关闭
讲堂
算法训练营
Python 进阶训练营
企业服务
极客商城
客户端下载
兑换中心
渠道合作
推荐作者
当前播放: 27 | channel的关闭和广播
00:00 / 00:00
标清
  • 标清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看

Go语言从入门到实战

共55讲 · 55课时,约700分钟
6092
免费
01 | Go语言课程介绍
免费
02 | 内容综述
免费
03 | Go语言简介:历史背景、发...
免费
04 | 编写第一个Go程序
免费
05 | 变量、常量以及与其他语言...
06 | 数据类型
07 | 运算符
08 | 条件和循环
09 | 数组和切片
10 | Map声明、元素访问及遍历
11 | Map与工厂模式,在Go语言...
12 | 字符串
13 | Go语言的函数
14 | 可变参数和defer
15 | 行为的定义和实现
16 | Go语言的相关接口
17 | 扩展与复用
18 | 不一样的接口类型,一样的...
19 | 编写好的错误处理
20 | panic和recover
21 | 构建可复用的模块(包)
22 | 依赖管理
23 | 协程机制
24 | 共享内存并发机制
25 | CSP并发机制
26 | 多路选择和超时
27 | channel的关闭和广播
28 | 任务的取消
29 | Context与任务取消
30 | 只运行一次
31 | 仅需任意任务完成
32 | 所有任务完成
33 | 对象池
34 | sync.pool对象缓存
35 | 单元测试
36 | Benchmark
37 | BDD
38 | 反射编程
39 | 万能程序
40 | 不安全编程
41 | 实现pipe-filter framew...
42 | 实现micro-kernel frame...
43 | 内置JSON解析
44 | easyjson
45 | HTTP服务
46 | 构建RESTful服务
47 | 性能分析工具
48 | 性能调优示例
49 | 别让性能被锁住
50 | GC友好的代码
51 | 高效字符串连接
52 | 面向错误的设计
53 | 面向恢复的设计
54 | Chaos Engineering
55 | 结束语
本节摘要
展开

精选留言(12)

  • 开始有点困扰,如果channel里的数据没有取完,这时producer关闭了channel,receiver能继续取数据么?
    然后实验了一下:发现当receivers从channel取完了数据,producer的colse(channel)才会被执行,即close(channel)会阻塞至channel中数据全部被取完。
    不知道对不对,请老师指点。多谢!
    1
  • 2019-03-24
    老师您好。
    传参 chan的时候,指针传参和值传参,看起来好像都可以work,而且复用的还是同一个通道。

    那对于chan的值传参,copy的是什么?

    作者回复: 这个在前面的课程中讲到过,chan是一个结构,这个结构在传递时是被复制的,其中的指针成员也会被复制到新的chan中,所以新旧两个chan会指向同一个内存区域

    1
  • 2019-11-05
    对于通道的okidiom,ok我更愿意理解为是否有数据可以接收,对于同步通道来说,接发都是阻塞的,接收数据不阻塞了要么是有一端发送了数据,要么是通道close了,所以对于同步通道ok为false,那么就是通道关闭了,对于异步通道来说,通道close了,但是通道中还有数据存在,这个时候接收ok还是为true,只有当没有数据可以接收了,ok才为false。
    对于closed和nil的通道:
    1.对于closed的通道,发送数据会panic
    2.对于closed的通道,同步通道会读出零值,异步通道如果有缓存数据读出缓存数据,没有缓存数据读出零值
    3.对于nil通道,读和写都会阻塞,可以利用这一点,在通道多路选择的时候,将读完数据的通道置空,判断所有通道都为nil之后才退出。
    展开
  • 2019-10-21
    消费者可以通过 data,ok<-ch 来判断通道是否关闭, 生产者如何判断通道是否关闭?

    func TestCloseChannel(t *testing.T) {
        var wg sync.WaitGroup
        ch := make(chan int)
        dataProducer(ch, &wg)
        dataReceiver(ch, &wg)
            // 已经关闭通道, 生产者如何判断
        close(ch)
        wg.Wait()
    }
    展开

    作者回复: 通道应该由生产者来关闭,在关闭的channel上发送数据程序会panic

  • 2019-09-26
    老师,请教一个问题,如果做爬虫程序,其实程序启动就是死循环,初始化channel容量10个,有新数据就添加到channel里,然后一直不关闭,应该也不会有问题吧

    作者回复: 这部分不会有问题。

  • 2019-08-08
    跟着老师一起手动敲代码,越瞧越来劲
  • 2019-07-09
    func TestCloseChannel(t *testing.T) {
        var wg sync.WaitGroup
        ch := make(chan int)

        wg.Add(1)
        dataProducer(ch, &wg)
        wg.Add(1)
        dataReceiver(ch, &wg)
        wg.Add(1)
        dataReceiver(ch, &wg)
        wg.Add(1)
        dataReceiver(ch, &wg)
        wg.Wait()
    }

    想知道,为什么后面的两个 dataReceiver 也能得到数据, 难道这三个dataReceiver不是串行执行的吗?我的理解是第一个 dataReceiver 会把 dataProducer 产生的所有数据都读完 才退出。
    展开

    作者回复: 虽然,语句是串行的,是线程的调度不是

  • 2019-06-25
    老师,当发送操作在执行的时候发现空的通道中,正好有等待的接收操作,那么它会直接把元素值复制给接收方,实际是这样的吗

    作者回复: 实际上和方法调用的直接传递复制是不同的,还是通过chan来完成的

  • 2019-06-14
    wg是不是要设置一下超时时间呢

    作者回复: waitgroup 方法是没有timeout可以设置的。你可以通过后面课程介绍的取消任务相关的内容自己实现一个有超时的等待(参见select部分内容)

  • 2019-04-05
    func serviceOne() string {
        time.Sleep(time.Millisecond * 50)
        return "service 1 done"
    }

    func channelserviceone_2nd() chan string {
        retCh := make(chan string, 1)
        go func() {
            ret := serviceOne()
            fmt.Println("returned result.")
            retCh <- ret
            fmt.Println("service exited.")
        }()
        return retCh
    }

    func TestSelect(t *testing.T) {
        select {
        case ret := <-channelserviceone_2nd():
            t.Log(ret)
        case <-time.After(time.Millisecond * 49):
            t.Log("time out")
        }
    }

    Output:
    === RUN TestSelect
    returned result.
    service exited.
    --- PASS: TestSelect (0.05s)
        /Users/stevenfung/Documents/code/go/src/github.com/CrazyPassion/go/helloworld/test/goroutine/goroutine_test.go:115: time out
    PASS
    ok     github.com/CrazyPassion/go/helloworld/test/goroutine    0.058s
    Success: Tests passed.
    老师,请教下这个问题,这个想不明白。按说serviceOne等待是50ms,49ms会超时,觉得应该看不到channelserviceone_2nd里面的打印,但是现在可以看到,并且也看到了超时的打印,这个是为什么?
    展开

    作者回复: 这是因为你用的是buffered chan他是非阻塞的。所以只要外面的主协程在退出前能有时间让他运行完,他就可以输出。
    你可以在TestSelect最后退出前加一个sleep 1秒,你就会发现更短的timeout一样会输出那些信息

  • 2019-03-20
    type MyChan struct {
        Chid int
        Msg string
    }

    func dataProducer1(ch chan MyChan, wg *sync.WaitGroup) {
        go func() {
            for i := 0; i < 10; i++ {
                ch <- MyChan{i, "msg"}
            }
            close(ch)
            wg.Done()
        }()
    }

    func TestCloseChannel1(t *testing.T) {
        var wg sync.WaitGroup
        ch := make(chan MyChan)
        wg.Add(1)
        dataProducer1(ch, &wg)
        wg.Add(1)
        dataReceiver1(ch, &wg)
        wg.Wait()
    }

    先模仿老师的代码。
    展开
  • 2019-03-20
    channel可以放自定义类型吗?

    作者回复: 可以的