3

For example I have this code:

package main

import (
    "fmt"
)

func main() {

    c1 := make(chan interface{})
    close(c1)
    c2 := make(chan interface{})
    close(c2)

    var c1Count, c2Count int
    for i := 1000; i >= 0; i-- {
        select {
        case <-c1:
            c1Count++
        case <-c2:
            c2Count++
        }

    }
    fmt.Printf("c1Count: %d\nc2Count: %d\n  ", c1Count, c2Count)
}

When running, the output will be:

c1Count: 513
c2Count: 488

The thing I don't know is: we create c1 and c2 channel without doing anything. Why in select/case block, c1Count and c2Count can increase value ?

Thanks

Trần Kim Dự
  • 5,872
  • 12
  • 55
  • 107

1 Answers1

4

The Go Programming Language Specification

Close

After calling close, and after any previously sent values have been received, receive operations will return the zero value for the channel's type without blocking. The multi-valued receive operation returns a received value along with an indication of whether the channel is closed.


You are counting zero values.

For example,

package main

import (
    "fmt"
)

func main() {

    c1 := make(chan interface{})
    close(c1)
    c2 := make(chan interface{})
    close(c2)

    var c1Count, c2Count int
    var z1Count, z2Count int
    for i := 1000; i >= 0; i-- {
        select {
        case z1 := <-c1:
            c1Count++
            if z1 == nil {
                z1Count++
            }

        case z2 := <-c2:
            c2Count++
            if z2 == nil {
                z2Count++
            }
        }

    }
    fmt.Printf("c1Count: %d\nc2Count: %d\n", c1Count, c2Count)
    fmt.Printf("z1Count: %d\nz2Count: %d\n", z1Count, z2Count)
}

Playground: https://play.golang.org/p/tPRkqXrAFno

Output:

c1Count: 511
c2Count: 490
z1Count: 511
z2Count: 490

The Go Programming Language Specification

For statements

For statements with range clause

For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil, the range expression blocks forever.

Close is useful with a for statement with a range clause.

peterSO
  • 158,998
  • 31
  • 281
  • 276
  • Understood. So that the reason why we will use close channel pattern right ? – Trần Kim Dự Jan 19 '19 at 10:18
  • And one more question is: what is difference between 2 methods: one is using close channel pattern (create close channel, at outside of loop, when done, we push an message into this close channel). And one is check directly inside select/case block (`case value, ok := <-c1:`) – Trần Kim Dự Jan 19 '19 at 10:27
  • Use `close` channel when it is useful. See my revised answer. – peterSO Jan 19 '19 at 10:28
  • See https://stackoverflow.com/questions/8593645/is-it-ok-to-leave-a-channel-open/8593986#8593986 – peterSO Jan 19 '19 at 10:40