Golang, with 17 short code fragments, understand the basics of channel


See an article on the net, summary of very good, in this collation record.

The basic concept

About pipeline Channel

  1. Channels are used to synchronize functions that are executed concurrently and provide some mechanism for them to communicate by value.
  2. Some features of Channels: The element type, container (or buffer), and direction of the pass through Channels are specified by the “<-” operator.
  3. C <-123, enter the value 123 into pipe C, <-c, read the value of pipe C to the left, value :=<-c, and then read into the value of pipe C.

Pipe classification

An important difference between unbuffered and buffered channels is that one is synchronous and the other is asynchronous.

Such as:

C1 :=make(chan int) null c2:=make(chan int,1) nullCopy the code

For example: c1 < 1

  • Unbuffered: not only does it put 1 in c1, but it does not continue until c1<-1 is taken over by another ctrip <-c1, otherwise it is blocked.
  • Buffered: c2<-1 does not block, because the buffer size is 1(actually the buffer size is 0), and only blocks if the second value is placed before the first value is taken away.

example

Demonstrates what a channel looks like without caching and with caching

Func test0(){/** done := make(chan bool) /** done1 := make(chan bool,1) /** buffed */  println(done,done1) }Copy the code

Example of deadlock without buffering in the same main

Func test1() {/** Compile error set, Done := make(chan bool) done<-true /* */ println(" done ")}Copy the code

Demonstrates a deadlock example of an input statement but no read statement

Func test2() {/** COMPILE error, block main process */ ** demo only input statements, */ done := make(chan bool) done<-true/println(" done ")}Copy the code

Demonstrates a deadlock example of a read statement but no input statement

Test3 () {make(chan bool) <-done /** Done is empty, so wait for */ println(" done ")}Copy the code

To demonstrate, coroutine blocking does not affect main

Func test4() {/** compile with */ /** demonstration, coroutine blocking, */ done := make(chan bool) go func() {<-done /** ** ** ** ** * println(" done ") /** * console output: ** done */}Copy the code

Based on test4, an unbuffered channel blocks in the coroutine Go routine

Func test5() {/** compiled by */ /** based on test4, */ done := make(chan bool) go func() {println(" I might do this ") /** done<-true /** */ println(" I will never print ") <-done /** This will not go unless it is read in another coroutine, or in main */}() println(" done ")}Copy the code

Test5 is used as a demo to delay the completion of main

Func test6() {/** */ done := make(chan bool) go func() {println(" I will never print ") done<-true */ println(" I will never print ") <-done /** * () time.sleep (time.second * 1) /** add delay 1 Second */ println(" done ") /** * console output: * If you block in the go routine, you may not output the content before the blocking statement. * Because the main has run out, so wait for the go routine */}Copy the code

Demonstrates that unbuffered channels receive fill and receive in different locations

Func test7() {make(chan bool) go func() {done<-true /** until <-done Println (" I will never print unless <-done is executed ")}() <-done /** received here, before the output is complete, then the above statement will go through */ println(" done ") /** * console output: * I will never output unless <-done is executed * completed */}Copy the code

Demonstrates the impact of unbuffered channels receiving in different places

*/ done := make(chan bool) go func() {done<-true /** until, <-done Otherwise this will block */ println(" I will never print unless <-done is executed ")}() println(" done ") <-done /** here to receive, after the output is finished */ /** * console output: * done * I will never output unless <-done executes */}Copy the code

Close does not block an uncached channel

Func test9() {func test9() {func test9() {func test9() { */ done := make(chan bool) close(done) //done<-true / */ println(" done ")}Copy the code

If close is used in the Go routine, a channel that has no cache will not be blocked

Func test10() {/** * set the channel to */ /**. */ done := make(chan bool) go func() {close(done)}() //done<-true /** */ println(" done ")}Copy the code

Example of a buffered channel that does not block

Func test11() {/** done := make(chan bool,1) done<-true <-done println(" done ")}Copy the code

An example of a buffered channel blocking

Func test12() {make(chan bool,1) // done<-true /** Println (" done ")} is buffered, but blocks if read without input.Copy the code

An example of a buffered channel blocking

*/ done := make(chan bool,1) done<-true done<-false /** */ println(" done ")} */ println(" done ")}Copy the code

Example of a buffered channel that does not block

Func test14() {/** done := make(chan bool,1) done<-true / */ println(" done ")}Copy the code

If a buffered channel is used in go Routine, you must delay it properly; otherwise, the output will be too late. Since main has run out, delay the channel for a while and wait for the Go routine

*/ done := make(chan bool,1) go func() {/** does not block */ Println (" I may print done<-true ") done< -done block */ println(" I may print done<-true ") }() time.sleep (time.second * 1) /** 1 Second delay, routine */ println(" done ") /** * * I may output oh * I may output oh * complete */ /** * Conclusion: * If you use a buffered channel in go routine, you must delay it properly, otherwise it will be too late to output the channel. * Because main has already run out, delay the channel for a while and wait for go routine */}Copy the code

Multiple channel pattern

func getMessagesChannel(msg string, delay time.Duration) <-chan string { c := make(chan string) go func() { for i := 1; i <= 3; I ++ {c < -ftt.sprintf ("%s %d", MSG, I) time.sleep (time.millisecond * delay) /** When will the next c type */}}() return c} func test16() {/** compiled via */ /** * complex demo example */ /** multi-channel mode */ c1 := C2 := getMessagesChannel("第 ", 600) c2 := getMessagesChannel("第 ", 500) c3 := getMessagesChannel("第 ", 600) C1 blocks C2, and C2 blocks C3 */ /** so it always prints c1 first, then C2, and then c3 */ for I := 1; i <= 3; Println (<-c1) /** Block c2 unless c1 has input,c3 */ println(<-c2) /** Unless c2 has input, Otherwise it blocks the following c3 */ println(<-c3) /** unless c3 has an input value, it blocks the next loop, and so on */} /** * Because * the getMessagesChannel function is delayed after the input value, in the second round and after * because the next C3 is not entered until 5 seconds later, it blocks the first 5 seconds of the second round, and so on. */ /** Change: if the delay in getMessagesChannel is placed before the input value, c3 will always wait 5 seconds before output */}Copy the code

Test15 based modifications, complex examples, multi-channel selection, delay after input

Func test17() {/** compiled by */ /** complex demo sample modified in test15 */ /** multi-channel selection, */ c1 := getMessagesChannel(" first ", 600) c2 := getMessagesChannel(" second ", 500) c3 := getMessagesChannel(" third ", 500) For I := 1; for I := 1; for I := 1; for I := 1; i <= 9; i++ { select { case msg := <-c1: println(msg) case msg := <-c2: println(msg) case msg := <-c3: Println (MSG)}} /** * the result of this program is: * second 1, third 1, first 1, second 2, first 2, second 3, first 3, third 2, third 3 */ The first three outputs, "first", "second", "third", all have, and * are output in random order, because the coroutine scheduling, the fourth, fifth, and sixth times, because the "second" delay is only 500ms, * is smaller than 600ms and 5000ms, so it output first, then "first", at this time "third" can not output. * Because it's still waiting 5 seconds. After another 500ms, the "third" 5 seconds have not run out, so continue to output "first", * after another 100ms, 500+100=600, "second" is also finished again, so output. At this point, "first" and "second" have * printed all three values of the pipe, 9-7 = 2, and the remaining two are "third". At this point, the first 5000ms is completed, * and, 500-600-600 = 3800ms, when reached, "third" output, 5 seconds later, the last "third output" */}Copy the code

enjoy!