I spent several hours to figure out some conceptions about channel tonight
1. buffered channel and non-buffered channel
buffered channel
bufferedchan := make(chan int, 1)
when adding element into bufferedchan, it will not blocked if it is not full.
for example:
package main import "fmt" func main() { messages := make(chan string, 1) messages <- "buffered" fmt.Println("quit!") }
the program won't block and the answer is:
quit!
2.channel is thread safe, and we can read data from a closed channel
package main import "fmt" func main() { jobs := make(chan int, 5) done := make(chan bool) go func() { ------------------------------- (Part I) fmt.Println("enter go routinue") for { j, more := <-jobs if more { fmt.Println("received job", j) } else { fmt.Println("received all jobs") done <- true return } } }() jobs <- 1 ------------------------------- (part II) jobs <- 2 jobs <- 3 close(jobs) fmt.Println("sent all jobs and closed")
<-done ------------------------------- (Part III) }
the result is:
sent all jobs and closed
enter go routinue
received job 1
received job 2
received job 3
received all jobs
firstly, it executes (Part II) and stop at <-done.
and then a child routinue executes (Part I) and done<-true.
Now the channel done is actived and continue to execute.
*If the channel jobs is not closed in main, the statement "j, more := <-jobs" in (Part I) will block. the deadlock will happen.
*If we don't set "<-done" in main, main will not wait the child routinue to finish.
3. range iterates buffered channel seeing https://gobyexample.com/range-over-channels
package main import "fmt" func main() { queue := make(chan string, 2) queue <- "one" queue <- "two" close(queue) for elem := range queue { fmt.Println(elem) } fmt.Println("done!") }
if we don't close the queue, it will block in "elem := range queue".
4. a closed channel won't block; we can't write to it, but we can read from it infinitly. the read value is always 0 value like 0/false/nil
package main import "fmt" func main() { queue := make(chan int, 2) queue <- 10 queue <- 20 close(queue) for i := 0; i < 10; i++ { fmt.Println(<-queue) } fmt.Println("done!") }
the result is
10
20
0
0
0
0
0
0
0
0
done!