Go Series Tutorial--22. Channels (channel)

Source: Internet
Author: User
Tags sleep function
This is a creation in Article, where the information may have evolved or changed. Welcome to the 22nd chapter of [Golang Series Tutorial] (HTTPS://STUDYGOLANG.COM/SUBJECT/2). In [previous tutorial], we explored how to use Go https://studygolang.com/articles/12342 (goroutine) to implement concurrency. We then learn channel in this tutorial to learn how to communicate through the channel to the Go process. # # What is a channel? A channel can be imagined as a conduit for communication between Go processes. Like the water in a pipe flows from one end to the other, by using a channel, the data can also be sent from one side and received at the other end. # # Channel declaration all channels are associated with a type. A channel can only transport this type of data, while transporting other types of data is illegal. ' Chan t ' represents a channel of type ' t '. The 0 value of the channel is ' nil '. The 0 value of the channel is useless, and you should define the channel with ' make ' as you did with the map and slice. Write the code below to declare a channel. "' Gopackage mainimport" FMT "Func Main () {var a chan intif a = = nil {fmt. PRINTLN ("Channel A is nil, going to define it") A = make (chan int) fmt. Printf ("Type of A is%T", a)}} "[Online Run Program] (Https://play.golang.org/p/QDtf6mvymD) because the channel's 0 value is ' nil ', in line 6th, the value of channel ' a ' is ' nil '. The program then executes the statement within the IF statement, defining the channel ' a '. The ' a ' in the program is a channel of type int. The program will output: "Channel A is nil, the going to define it Type of an is Chan int '" Short declaration is often also a concise and effective way to define the channel. "' Goa: = make (chan int) ' is a line of code that also defines an int type of channel ' a '. # # is sent and received through the channel as shown below, which sends and receives data over the channel. "' Godata: = <-A//Read channel A A <-data//write the arrow next to channel a '"The direction specifies whether to send data or receive data. In the first line, the arrows are outward pointing to ' a ', so we read the value of the channel ' a ' and store the value in the variable ' data '. In the second line, the arrow points to ' a ', so we're writing the data to channel ' a '. # # Send with receive default is blocked send and receive default is blocked. What does that mean? When the data is sent to the channel, the program control will block at the statement where the data is sent, until there are other Go threads reading from the channel to the data before it is unblocked. Similarly, when reading a channel's data, if there is no other process to write the data to this channel, then the read procedure will be blocked. This feature of the channel enables efficient communication between the Go process, without the need for explicit locks or condition variables that are common in other programming languages. The # # Channel code example theory is enough:). Then write some code to see how the process communicates through the channel. We can actually rewrite the program we wrote when we learned [Go] (https://studygolang.com/articles/12342) in the previous chapter, and now we use the channel here. First, refer to the program in the previous tutorial. "' Gopackage mainimport (" FMT "" Time ") func hello () {fmt. Println ("Hello World Goroutine")}func main () {go Hello () time. Sleep (1 * time. Second) fmt. Println ("Main function")} "[Running Program Online] (https://play.golang.org/p/u9zzusql8-) This is the code for the previous article. We used hibernation so that the Go master process was waiting for the end of the Hello coprocessor. If you don't understand it, it is recommended that you read the previous tutorial [Go https://studygolang.com/articles/12342]. We then use the channel to rewrite the above code. "' Gopackage mainimport (" FMT ") func hello (done chan bool) {FMT. Println ("Hello World Goroutine") did <-True}func main () {done: = make (chan bool) go-Hello (done) <-donefmt. Println ("Main function")} "[Running Program online] (httPS://PLAY.GOLANG.ORG/P/I8GOKV6ZMF) in the above procedure, we created a bool type channel ' done ' on line 12th and passed ' done ' as a parameter to the ' Hello ' Association. In line 14th, we receive the data through the channel ' done '. This line of code is blocked and the program does not skip to the next line of code unless there is a process to write the data to ' done '. Therefore, this does not need to use the previous ' time. Sleep ' to prevent the Go Main association from exiting. The ' <-done ' code receives the data through the process of ' done ', but does not use the data or store the data in a variable. This is entirely legal. Now our Go main process has been blocked, waiting for the channel ' done ' to send the data. The channel is passed as a parameter to the coprocessor ' hello ', ' hello ' prints out ' Hello World goroutine ' and then writes the data to ' done '. When the write is complete, the Go master process receives the data through the channel ' done ', so it unlocks the blocking state and prints the text ' main function '. The program output is as follows: "' Hello World goroutine main function '" We have slightly modified the program to add the sleep function in the ' Hello ' association thread in order to better understand the concept of blocking. "' Gopackage mainimport (" FMT "" Time ") func hello (done chan bool) {FMT. Println ("Hello go routine is going to sleep") time. Sleep (4 * time. Second) fmt. Println ("Hello go routine awake and going to write") did <-True}func main () {done: = make (chan bool) fmt. Println ("Main going to call Hello go goroutine") Go-Hello (done) <-donefmt. Println ("Main received data")} "[Online Run Program] (Https://play.golang.org/p/EejiO-yjUQ) in the above program, we are to ' hello ' letter4 seconds of hibernation (line 10th) was added to the number. The program will first print ' Main going to call hello Go goroutine '. The ' hello ' process is then turned on to print ' Hello go routine is going to sleep '. After printing, the ' Hello ' Association sleeps for 4 seconds, and during this time, the main coprocessor blocks on the ' <-done ' line, waiting for data from channel ' done '. After 4 seconds, print ' Hello go routine awake and going to write ', then print ' Main received data '. # # Another example of a channel we'll write a program to better understand the channel. The program calculates the sum of squares of each bit in a number with the cubic and then sums the squares together with the cubic and adds and prints them out. For example, if the output is 123, the program calculates the output as follows: "' Squares = (1 * 1) + (2 * 2) + (3 * 3) cubes = (1 * 1 * 1) + (2 * 2 * 2) + (3 * 3 * 3) output = Squares + cubes = 50 "' We're going to build the program: the sum of squares is computed in a separate go, while in the other, the cube is computed and, finally, the sum of squares and cubes are added to the go main process. "' Gopackage mainimport (" FMT ") func calcsquares (number int, Squareop chan int) {sum: = 0for number! = 0 {digit: = number % 10sum + = digit * Digitnumber/= 10}squareop <-sum}func calccubes (number int, Cubeop chan int) {sum: = 0 for number ! = 0 {digit: = number% 10sum + = digit * Digit * digitnumber/= 10}cubeop <-sum} func main () {number: = 589sqrch: = Make (chan int) Cubech: = make (chan int) go calcsquares (number, sqRCH) Go calccubes (number, Cubech) squares, cubes: = <-sqrch, <-cubechfmt. Println ("Final output", squares + Cubes)} "[Running Program Online] (Https://play.golang.org/p/4RKr7_YO_B) on line 7th, function ' Calcsquares ' Calculates the sum of squares of a number per bit and sends the result to the channel ' Squareop '. Similarly, the 17th line of the function ' Calccubes ' computes a number per bit of cubic and sends the result to the channel ' Cubop '. The two functions run in separate threads (lines 31st and 32nd), each with arguments for passing channels to write data. The Go master will wait on line 33rd for data coming from two channels. Once the data is received from both channels, the data is stored in the variable ' squares ' and ' cubes ', and the final result is computed and printed. The program outputs: "Final output 1536 ' # # # # # # # # # # # # A deadlock is a key consideration to use the channel. When the go process sends data to a channel, it is supposed that there will be other go processes to receive the data. If not, the program will trigger panic at run time, creating a deadlock. Similarly, when a go process is waiting to receive data from a channel, we expect the other go coprocessor to write data to that channel, or the program will trigger panic. "' Gopackage MainFunc Main () {ch: = make (chan int) ch <-5}" [Online Run Program] (Https://play.golang.org/p/q1O5sNx4aW) in the above program, We created a channel ' ch ', followed by the next line ' ch <-5 ', and we sent ' 5 ' to this channel. For this program, no other co-process receives data from ' ch '. So the program triggers panic, and the following run-time error occurs. "' Fatal Error:all Goroutines is asleep-deadlock!goroutine 1 [chan send]: Main.main ()/tmp/sandbox249677995/main.go:6 +0x80 ' # # One-way channel we are currently discussing the channel is two-way channel, that is, through the channel can both send data and receive data. In fact, it canTo create a one-way channel that can send or receive data only. "' Gopackage mainimport" FMT "func senddata (sendch chan<-int) {SENDCH <-10}func main () {sendch: = Make (chan<- int) go SendData (SENDCH) fmt. Println (&LT;-SENDCH)} "[Online Run Program] (Https://play.golang.org/p/PRKHxM-iRK) above the 10th line of the program, we created the only send (send only) channel ' SENDCH '. ' chan<-int ' defines the only Messenger, because the arrow points to ' Chan '. In line 12th, we tried to receive the data through the only Messenger, so the compiler gave an error: "' Main.go:11:invalid Operation: &LT;-SENDCH (receive from send-only type chan<-int) ' "* * Everything is going well, but what's the point of a messenger that can't read the data? * * * This requires the use of channel Conversion. Converting a two-way channel into a messenger or a receive only channel is OK, but not in the opposite direction. * * "Gopackage mainimport" FMT "func senddata (sendch chan<-int) {SENDCH <-10}func main () {cha1: = make (chan int) Go SendData (CHA1) fmt. Println (&LT;-CHA1)} "[Running Program Online] (https://play.golang.org/p/aqi_rJ1U8j) in line 10th of the above program, we created a two-way channel ' CHA1 '. In line 11th ' CHA1 ' is passed as a parameter to the ' SendData ' Association. In line 5th, the parameter ' sendch chan<-int ' in the function ' SendData ' converts ' cha1 ' to a only-send channel. So the channel in the ' SendData ' association thread is a only messenger, and in the Go Main association thread is a two-way channel. The program eventually prints out ' 10 '. # # Close channel and use for RANGE Traversal channel data sender can turn off the channel, notifying the receiver that the channel no longer has data sent over. When receiving data from a channel, the receiver can use one more variable to check if the channel is closed. "V, OK: = <-ch" Above the statement, if successfully received the channel sent data, then ' OK ' equals true. And if ' OK ' equals false, it means we're trying to read a closed channel. The value read from the closed channel will be a value of 0 for that channel type. For example, when a channel is an ' int ' type of channel, the value read from the closed channel will be ' 0 '. "' Gopackage mainimport (" FMT ") Func producer (CHNL Chan int) {for i: = 0; i <; i++ {chnl <-i}close (chnl)}func m Ain () {ch: = make (chan int) go producer (ch) for {V, OK: = <-chif OK = = False {break}fmt. Println ("Received", V, OK)} "[Running Program Online] (https://play.golang.org/p/XWmUKDA2Ri) in the above program, the ' producer ' Coprocessor writes the channel ' Chn1 ' from 0 to 9 , and then close the channel. The main function has an infinite for loop (line 16th), using the variable ' OK ' (line 18th) to check if the channel is closed. If ' OK ' equals false, the channel is closed and the for loop is exited. If ' OK ' equals true, the value of the received value and ' OK ' will be printed. "' Received 0 true Received 1 true Received 2 true Received 3 true Received 4 true Received 5 true Received 6 true Receive D 7 true Received 8 true Received 9 true ' for range ' loop is used to receive data from the channel before a channel is closed. Next we use the For Range loop to rewrite the above code. "' Gopackage mainimport (" FMT ") Func producer (CHNL Chan int) {for I : = 0; I < 10; i++ {chnl <-i}close (CHNL)}func main () {ch: = make (chan int) go producer (CH) for V: = Range ch {fmt. Println ("Received", V)}} "[Online Run Program] (https://play.golang.org/p/JJ3Ida1r_6) on line 16th, the for Range loop receives data from channel ' ch ' until the channel is closed. Once the ' ch ' is closed, the loop will automatically end. The program outputs: ' ' Received 0 Received 1 Received 2 Received 3 Received 4 Received 5 Received 6 Received 7 Received 8 Received 9 ' "We can use the for Range loop and rewrite the code in the section [another example of the channel] (#) to improve the reusability of the code." If you look closely at this code, you will find that the code for each digit in a number repeats within the ' calcsquares ' and ' Calccubes ' two functions. We'll pull this code out, put it in a separate function, and call it in parallel. "' Gopackage mainimport (" FMT ") func digits (number int, dchnl Chan int) {for number! = 0 {digit: = number% 10DCHNL <- Digitnumber/= 10}close (DCHNL)}func calcsquares (number int, Squareop chan int) {sum: = 0dch: = make (chan int) go digits (n Umber, DCH) for digit: = range DCH {sum + = digit * Digit}squareop <-sum}func calccubes (number int, Cubeop Chan int) {s Um: = 0dch: = make (chan int) go digits (number, DCH) for digit: = range DCH {sum + = digit * Digit * diGit}cubeop <-Sum}func Main () {number: = 589sqrch: = Make (Chan int.) Cubech: = make (chan int) go calcsquares (number, SQRC h) Go calccubes (number, Cubech) squares, cubes: = <-sqrch, <-cubechfmt. Println ("Final output", Squares+cubes)} "[Online Run Program] (https://play.golang.org/p/oL86W9Ui03) the ' digits ' function in the above program, Contains the logic to get a number of bits per digit, and ' calcsquares ' and ' calccubes ' two functions call ' digits ' concurrently. When the number of digits is counted, the 13th line closes the channel. The ' calcsquares ' and ' calccubes ' two processes use a for Range loop to listen to their channels separately until the channel is closed. Elsewhere in the program, the program will also output: "Final output 1536" is the end of the tutorial's content. There are other concepts about channels, such as buffer channels (Buffered channel), Worker pool, and select. We'll cover them in the next tutorial. Thanks for reading. Have a nice day. * * Previous tutorial-[Go] (https://studygolang.com/articles/12342) * * * Next tutorial-[buffered channel and working Pool] (https://studygolang.com/articles/12512) * *

via:https://golangbot.com/channels/

Author: Nick Coghlan Translator: Noluye proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

4,062 Reads
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.