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

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

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

    
     1
  • 黄三可
    2020-02-10
    本节中的dataProducer方法,waitGroup传入的是指针,为什么在方法体中使用时,不需要像传入int指针一样,写成*wg.Done()
    
    
  • 我姓蔡。
    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来完成的

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

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

    
    
  • Steven Fung
    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()
    }

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

    作者回复: 可以的

    
    
我们在线,来聊聊吧