关于chan的用法困惑

lorenwe · 2019-10-31 11:35:13 · 1792 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2019-10-31 11:35:13 的主题,其中的信息可能已经有所发展或是发生改变。

image.png

其中 ch = PrimeFilter(ch, prime) 这一句, chan可以赋值给chan类型吗?是怎么样的一个赋值过程呢?


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1792 次点击  ∙  1 赞  
加入收藏 微博
6 回复  |  直到 2019-11-05 15:21:06
jan-bar
jan-bar · #1 · 5年之前

没写过这么666的代码。但我的映像中,切片、map、interfere{}、chan等都是默认为地址,你看chan是需要make出来的,所以可以从这方面研究吧。

lorenwe
lorenwe · #2 · 5年之前
jan-barjan-bar #1 回复

没写过这么666的代码。但我的映像中,切片、map、interfere{}、chan等都是默认为地址,你看chan是需要make出来的,所以可以从这方面研究吧。

一直很困惑 ch = PrimeFilter(ch, prime) 这段代码是怎么运行的

lorenwe
lorenwe · #3 · 5年之前
lorenwelorenwe #2 回复

#1楼 @jan-bar 一直很困惑 `ch = PrimeFilter(ch, prime) ` 这段代码是怎么运行的

虽然看起来很奇怪,但真的能跑起来,如果直接写 PrimeFilter(ch, prime) 输出的结果是不对的

buguang01
buguang01 · #4 · 5年之前

你把ch看成一个对象变量就行了,这段代码就是为每找到一个素数,就为从自然数读取中的过滤器上加一道,所以找到的素数越多,那么Chan的连路也会越多,对应启动的go协程也会越多 但是比一般的查找逻辑优化了CPU,使用更多的内存。

jan-bar
jan-bar · #5 · 5年之前
package main

import "fmt"

func main() {
    ch := g()
    for i := 1; i <= 100; i++ {
        pp := <-ch
        fmt.Printf("%v:%v\n", i, pp)
        ch = p(i, ch, pp)
    }
}

func g() chan int {
    ch := make(chan int)
    go func() { // 本协程只会一致往cnt=1那个接收协程里面写入
        for i := 2; ; i++ {
            ch <- i
        }
    }()
    return ch
}

func p(cnt int, in <-chan int, p int) chan int {
    out := make(chan int)
    go func(cnt int) { // cnt表示哪个go func运行
        for { // p 和 cnt有对应关系,详细可以看打印结果
            if i := <-in; i%p != 0 {
                fmt.Printf("cnt:%d,out<-%d,%d %% %d != 0\n", cnt, i, i, p)
                out <- i // 写入out会作为下一个协程的in
            }
        }
    }(cnt)
    return out
}

(ps:你不发文本,我懒得敲函数名了,嘿嘿。)仔细研究了一下你这个程序,确实666。因为发送协程一直在g里面写入,接收有很多个协程,每个协程接收的数据是上一个接收协程判断成功后发送的数据,因此那个过滤的func确实能达到过滤的效果。就像一堆小球滚下楼梯,每个楼梯都要判断哪些小球能滚到下个楼梯,一些不满足条件的会在中途某些接收协程里面踢出掉,这些踢出的是不会传到下个接收协程。这种程序一般用于学习吧,理解起来是有点绕。

多说一句,这些中途的chan貌似没办法close掉,而协程一直存在,不会被GC掉,该程序如果不退出那这些chan就要算内存泄漏了。

lorenwe
lorenwe · #6 · 5年之前
jan-barjan-bar #5 回复

```go package main import "fmt" func main() { ch := g() for i := 1; i <= 100; i++ { pp := <-ch fmt.Printf("%v:%v\n", i, pp) ch = p(i, ch, pp) } } func g() chan int { ch := make(chan int) go func() { // 本协程只会一致往cnt=1那个接收协程里面写入 for i := 2; ; i++ { ch <- i } }() return ch } func p(cnt int, in <-chan int, p int) chan int { out := make(chan int) go func(cnt int) { // cnt表示哪个go func运行 for { // p 和 cnt有对应关系,详细可以看打印结果 if i := <-in; i%p != 0 { fmt.Printf("cnt:%d,out<-%d,%d %% %d != 0\n", cnt, i, i, p) out <- i // 写入out会作为下一个协程的in } } }(cnt) return out } ``` ### (ps:你不发文本,我懒得敲函数名了,嘿嘿。)仔细研究了一下你这个程序,确实666。因为发送协程一直在g里面写入,接收有很多个协程,每个协程接收的数据是上一个接收协程判断成功后发送的数据,因此那个过滤的func确实能达到过滤的效果。就像一堆小球滚下楼梯,每个楼梯都要判断哪些小球能滚到下个楼梯,一些不满足条件的会在中途某些接收协程里面踢出掉,这些踢出的是不会传到下个接收协程。这种程序一般用于学习吧,理解起来是有点绕。 ### 多说一句,这些中途的chan貌似没办法close掉,而协程一直存在,不会被GC掉,该程序如果不退出那这些chan就要算内存泄漏了。

感谢

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传