awesome way to make use of nil channel

Awesome way to make use of nil channel

common

Send and receive operations on a nil channel block forver. It’s a well documented behavior

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
	"fmt"
)

func main() {
	var ch chan int

	go func() {
		fmt.Println("ready to read from ch")
		fmt.Printf("get val: %v\n", <-ch)
	}()
	fmt.Println("ready to write val to ch")
	ch <- 17
}

got output image.png

awesome usage

This behavior can be used as a way to dynamically enable and disable case blocks in a select statement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import(
	"fmt"
	"time"
)

func main() {  
    inch := make(chan int)
    outch := make(chan int)

    go func() {
	// (0) `in != nil`
        var in <- chan int = inch
        var out chan <- int
        var val int
        for {
	    // enable and disable `out`, `in`
            select {
	    // (1)(3) out == nil => { blocking }
	    // (2)(4) out != nil => { out <- val; in != nil } 
            case out <- val:
                out = nil
                in = inch

	    // (1)(3) in != nil => { out != nil; val <- in; in == nil }
	    // (2)(4) in == nil => { blocking }
            case val = <- in:
                out = outch
                in = nil
            }
        }
    }()

    go func() {
	// (1) blocking
	// (2) result: 1
	// (3) blocking
	// (4) result: 2
        for r := range outch {
            fmt.Println("result:",r)
        }
    }()

    time.Sleep(0)
    inch <- 1
    inch <- 2
    time.Sleep(3 * time.Second)
}

ref

http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy