Go Channel Explanation

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Catalogue [−]

    1. Channel type
    2. Blocking
    3. Buffered Channels
    4. Range
    5. Select
      1. Timeout
    6. Timer and Ticker
    7. Close
    8. Synchronous
    9. Resources

The channel is a core type in go, and you can think of it as a conduit through which the core unit can send or receive data for communication (communication).

Its operator is the arrow <- .

12
Ch <-v    //Transmit value V to channel CH medium V: = <-ch  //Receive data from channel CH and assign data to V

(arrow pointing is the flow of data)

Just like the map and slice data types, the channel must first be created and reused:

1
 Make (chanint)

Channel type

The channel type is defined in the following format:

1
Channeltype "Chan" "Chan" "<-" "<-" "Chan" ElementType .

It includes three types of definitions. Optionally <- represents the direction of the channel. If you do not specify a direction, then the channel is bidirectional, either to receive data or to send data.

123
Chan T          //can receive and send data of type T Chanfloat64  //can only be used to send data of float64 type <-chan  int      //can only be used to receive data of type int

<-Always priority and the leftmost type are combined. (The <-operator associates with the leftmost Chan possible)

1234
Chan Chan int    //equivalent chan<-(chan int) Chan<-<-chanint  //equivalence chan<-(<-chan int)<-Chan <-chanint  //equivalence <-chan (<-chan int)chan (<-  Chanint)

Use make the Initialize channel, and you can set the capacity:

1
 Make (chanint, +)

The capacity (capacity) represents the maximum number of elements that the channel holds, representing the size of the channel's cache.
If no capacity is set, or if the capacity is set to 0, the channel is not cached, and only sender and receiver are ready for their communication (communication) to occur (Blocking). If the cache is set, it is possible that the send will not block until the buffer is full, and the receive will not block until the cache is empty. A nil channel does not communicate.

The channel can be closed by the built-in close method.

You can receive/send data in multiple goroutine from/to a channel without having to consider additional synchronization measures.

The channel can act as a first-in, first-out (FIFO) queue, and the order in which the data is received and sent is consistent.

The channel's receive supports multi-valued assignment, such as

1
V, OK: = <-ch

It can be used to check if the channel has been closed.

    1. Send statement
      The Send statement is used to send data to the channel, such as ch <- 3 .
      It is defined as follows:
12
"<-" Expression. Channel  = Expression.

The channel and expression must be evaluated before the communication (communication) begins (evaluated), such as the following (3+4) first calculates 7 and then sends it to the channel.

12345
 Make (chanint) defer Close (c) Go func () {c <- 3 + 4 } () I: = <-cfmt. Println (i)

Send pre-execution (proceed) communication (communication) has been blocked. As previously stated, a non-cached channel will only be executed when receiver is ready. If there is a cache and the cache is not full, send will be executed.

Continuing to send data to a channel that has already been close will cause run-time panic.

Sending data to the nil channel is consistently blocked.

    1. Receive operator
      <-chUsed to receive data from channel CH, the expression will be blocked until data can be received.

Receiving data from a nil channel will always be block.

Receiving data from a closed channel is not blocked, but returns immediately, and returns 0 of the element type (zero value) after receiving the sent data.

As mentioned earlier, you can use an additional return parameter to check if the channel is closed.

123
X, OK: = <-chx, ok = <-chvar x, OK = <-ch

If OK is false, indicates that the received X is the resulting 0 value, the channel is closed or empty.

Blocking

By default, send and receive are blocked until the other party is ready. This method can be used to synchronize in Gororutine without using the displayed lock or condition variable.

In the official case, x, y := <-c, <-c this sentence will wait until the result of the calculation is sent to the channel.

1234567891011121314151617181920
Import "FMT"funcSUM (s []intCChan int) {sum: =0 for_, V: =Ranges {sum + = v}c <-sum//Send sum to C}funcMain () {s: = []int{7,2,8,-9,4,0}c: = Make(Chan int)GoSUM (s[:Len(s)/2], c)GoSUM (s[Len(s)/2:], c) x, y: = <-c, <-c//Receive from CFmt. Println (x, Y, X+y)}

Buffered Channels

The second parameter of make specifies the size of the cache: ch := make(chan int, 100) .

By using the cache, you can avoid blocking and provide the performance of your application.

Range

for …… rangeStatements can handle channel.

 123456789101112131415161718 
 func  main () {go  func  () {time. Sleep (1  * time. Hour)} () c: = make  (chan  int ) go  func  () {for  i: =  0 ; I < ; i = i + 1  {c <-i}close  (c)} () for
         I: = range  c {fmt. Println (i)}fmt. Println ( "finished" )} 

range cThe resulting iteration value is the value sent in the channel, and it will iterate until the channel is closed. In the above example, if the close(c) comment is dropped, the program will always block in for …… range that line.

Select

selectStatement to select a set of possible send operations and receive operations to handle. It switch is similar, but is only used to handle communication (communication) operations.
It can be a case send statement, or a receive statement, or default .

receiveA statement can assign a value to one or two variables. It must be a receive operation.

A maximum of one is allowed default case , and it can be placed anywhere in the case list, although most of us will put it at the end.

1234567891011121314151617181920212223242526
Import "FMT"funcFibonacci (c, quitChan int) {x, Y: =0,1 for{Select{ CaseC <-x:x, y = y, x+y Case<-quit:fmt. Println ("Quit")return}}}funcMain () {c: = Make(Chan int) Quit: = Make(Chan int)Go func() { forI: =0; I <Ten; i++ {fmt. Println (<-c)}quit <-0} () Fibonacci (C, quit)}

If there is more than one case to deal with, such as having multiple channel to receive data at the same time, go will randomly select an instance processing (pseudo-random). If no case needs to be handled, it will be selected default to handle if default case present. If not default case , the select statement blocks until a case needs to be processed.

It should be noted that the operation on the nil channel will always be blocked, and if there is no default case, only the select of nil channel will be blocked.

selectStatement and switch statement, it is not a loop, it will only choose a case to handle, if you want to process the channel, you can add an infinite for loop outside:

123456789
 for {Select { case C <-x:x, y = y, x+y case <-quit:fmt. Println ("quit")return}}

Timeout

selectOne important application is the timeout process. Because we mentioned above, if there is no case to deal with, the SELECT statement will always be blocked. At this point we may need a timeout operation to handle the timeout situation.
In this example we will send a data to channel C1 in 2 seconds, but select set to 1 seconds timeout, so we will print out timeout 1 instead result 1 .

 1234567891011121314151617 
 import   "time"  import   "FMT"  func  main () {c1: = make  (chan  string ,  1 ) go  func  () {time. Sleep (time. Second * 2 ) C1 <- "Result 1" } () select  {case  res: = <-c1:fmt. Println (res) case  <-time. After (time. Second * 1 ): FMT. Println ( "Timeout 1" )}} 

In fact, it uses the time.After method, which returns a type <-chan Time of one-way channel, which sends a current time at a specified time to the returned channel.

Timer and Ticker

Let's take a look at the two channel of time.
A timer is a timer that represents a single event in the future, and you can tell the timer how long it will take you to wait, it provides a channel, and at that time in the future the channel provides a time value. In the following example, the second row blocks for about 2 seconds, until the time is up for the execution to continue.

123
Timer1: = time. Newtimer (time. Second * 2) <-timer1. Cfmt.println ("Timer 1 Expired")

Of course, if you just want to wait, you can use time.Sleep to achieve.

You can also use timer.Stop to stop the timer.

123456789
Timer2: = time. Newtimer (time. Second)gofunc() {<-timer2. Cfmt.println ("Timer 2 Expired")} () Stop2: = Timer2. Stop ()if stop2 {fmt. Println ("Timer 2 Stopped")}

tickeris a timed-triggered timer that sends an event (the current time) to the channel at an interval (interval), while the receiver of the channel can read events from the channel at a fixed interval. In the following example ticker is triggered every 500 milliseconds, you can observe the time of the output.

123456
Ticker: = time. Newticker (Time.millisecond * )gofunc() {forrange Ticker. C {fmt. Println ("Tick at", T)}} ()

Like a timer, ticker can also be stopped by means of a Stop method. Once it stops, the receiver will no longer receive data from the channel.

Close

The built-in close method can be used to close the channel.

Summarize the receiver operation of sender after the channel is closed.
If channel C has been closed, continuing to send data to it will result in panic: send on closed channel :

123456789101112
Import "Time" func  func()  {time. Sleep (Time. Hour)} ()C1c2Close (c)C 3}

However, from this closed channel, not only can read out the sent data, but also can continuously read the value of 0:

12345678
 Make (chanint, ten) c <- 1C <- 2close//1//2  //0//0

However, if range the channel is closed after reading, the For loop will jump out:

1234567
 Make (chanint, ten) c <- 1C <- 2close(c)forRange C {fmt. Println (i)}

You can determine whether a value is a value of i, ok := <-c 0 or a normal read by looking at the status of the channel.

12345
 Make (chanint, ten) Close (c) I, OK: = <-cfmt. Printf ("%d,%t"//0, False

Synchronous

The channel can be used for synchronization between Goroutine.
In the following example, main goroutine waits for the worker to complete the task by doing the channel. When the worker finishes the task, it simply sends a data to the channel to notify the main Goroutine task to complete.

12345678910111213141516171819
Import ("FMT""Time") func Chan bool) {time. Sleep (time. Second)//Notification task completed true}funcmake (chanbool, 1 Go worker (done)//wait for task to complete <-done}

Resources

    1. https://gobyexample.com/channels
    2. https://tour.golang.org/concurrency/2
    3. https:// Golang.org/ref/spec#select_statements
    4. https://github.com/a8m/go-lang-cheat-sheet
    5. /http devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/
    6. http://guzalexander.com/2013/12/06/ golang-channels-tutorial.html
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.