首页 > 其他 > 详细

奇怪的channel 的笔记

时间:2014-05-30 00:09:09      阅读:459      评论:0      收藏:0      [点我收藏+]

channel 不仅能够控制数据传输,还可以控制执行流。

1.  关闭的channel从来都不会阻塞

关闭的channel不能传数据但是可以接受数据,例子

```

package main

import "fmt"

func main() {
        ch := make(chan bool, 2)
        ch <- true
        ch <- true
        close(ch)

        for i := 0; i < cap(ch) +1 ; i++ {
                v, ok := <- ch
                fmt.Println(v, ok)
        }
}

```

 

接受的是默认空值。

替代性地,可以用range

```

package main

import "fmt"

func main() {
        ch := make(chan bool, 2)
        ch <- true
        ch <- true
        close(ch)

        for v := range ch {
                fmt.Println(v) // called twice
        }
}

```

当channel干枯后就会跳出循环流程,这个循环会执行两次。

 

但是select才是真功夫。

 

```

package main

import (
        "fmt"
        "sync"
        "time"
)

func main() {
        finish := make(chan bool)
        var done sync.WaitGroup
        done.Add(1)
        go func() {
                select {
                case <-time.After(1 * time.Hour):
                case <-finish:
                }
                done.Done()
        }()
        t0 := time.Now()
        finish <- true // send the close signal
        done.Wait()    // wait for the goroutine to stop
        fmt.Printf("Waited %v for goroutine to stop\n", time.Since(t0))
}

```

 

在调用done之前是不会真的等一个小时的。

但是这个程序也会有问题。就是finish 不是带缓冲的。如果接受者忘了加上select里面的语句的话,就会阻塞了。(比如开了100个goroutine,但是这送了99次之类的)

利用关闭了的channel是永远可以接受的特性,把代码改成下面这样。

```

package main

import (
        "fmt"
        "sync"
        "time"
)

func main() {
        const n = 100
        finish := make(chan bool)
        var done sync.WaitGroup
        for i := 0; i < n; i++ { 
                done.Add(1)
                go func() {
                        select {
                        case <-time.After(1 * time.Hour):
                        case <-finish:
                        }
                        done.Done()
                }()
        }
        t0 := time.Now()
        close(finish)    // closing finish makes it ready to receive
        done.Wait()      // wait for all goroutines to stop
        fmt.Printf("Waited %v for %d goroutines to stop\n", time.Since(t0), n)
}

```

话说这和没有finish通道不是一个效果么?不管了

实际上如果在通道里的东西,你从来不用,应该构造成空的结构体,就像下面的例子。

```

package main

import (
        "fmt"
        "sync"
        "time"
)

func main() {
        finish := make(chan struct{})
        var done sync.WaitGroup
        done.Add(1)
        go func() {
                select {
                case <-time.After(1 * time.Hour):
                case <-finish:
                }
                done.Done()
        }()
        t0 := time.Now()
        close(finish)
        done.Wait()
        fmt.Printf("Waited %v for goroutine to stop\n", time.Since(t0))
}

```

 

说明这个channel不包含东西。

2.  nil channel 永远都是阻塞的。

```

package main

func main() {
        var ch chan bool
        ch <- true // blocks forever
}

```

这是一个死锁。

接受的话也是死锁。
```
package main

func main() {
        var ch chan bool
        <- ch // blocks forever
}

```

先看到这,明天再来。

奇怪的channel 的笔记,布布扣,bubuko.com

奇怪的channel 的笔记

原文:http://www.cnblogs.com/ggaaooppeennngg/p/3758059.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!