Go language concurrency and Parallel Learning notes (iii)

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

The following design patterns and scenarios come from the ppt:https://talks.golang.org/2012/concurrency.slide on Goroutine on Google io

The sample code for this article is in: Https://github.com/hit9/Go-patterns-with-channel

Generator

In Python we can use yield keywords to make a function a generator, and in go we can use the channel to make generators (something like lazy load).

Of course, our channel is not simply to do the function of blocking the main line to use OH.

Here is an example of making an auto-increment integer generator, until the main line asks for data from the channel, we add the data to the channel

Func xrange () Chan int{//Xrange used to generate the self-increment of the integer    var ch chan int = make (chan int)    go func () {//out a goroutine for        I : = 0;; i++ {            ch <-i  //until channel request data, only add I to channel        }    } ()    return Ch}func main () {    Generator: = Xrange ()    for i:=0; i <; i++ {  //We generate 1000 self-increment integers!        FMT. Println (<-generator)    }}

It reminds me of the cute Python xrange , so I gave the generator the name!

Service of

For example, when we load a Web site, such as when we log on to Sina Weibo, our message data should come from a separate service, which is only responsible for returning a user's new message reminder.

Here is an example of use:

Func get_notification (User string) Chan string{   /    * * Here you can query the database for new messages, etc...    *    /notifications: = Make (chan string)    go func () {//Hang a channel out        notifications <-FMT. Sprintf ("Hi%s, Welcome to weibo.com!", user)    } ()    return Notifications}func main () {    Jack: = get_ Notification ("Jack")//  get Jack's message    Joe: = Get_notification ("Joe")//Get Joe's message    //Get the message back to    FMT. Println (<-jack)    FMT. Println (<-joe)}

Multi-channel composite

The above example uses a channel as the return value, which merges the channel data into a single channel. In this case, however, we need to output our return value sequentially (FIFO).

As below, we assume that we want to calculate a very complex operation 100-x , divided into three-way calculation, and finally unified in a channel to take out the results:

Func do_stuff (x int) int {//a relatively time-consuming thing, such as calculation of timing    . Sleep (time. Duration (Rand. INTN (Ten)) * time. MILLISECOND)//Analog calculation    return 100-x//If 100-x is a time-consuming calculation}func branch (x int) Chan int{//Each branch leaves a goroutine to do the calculation and flows the results into confidence  DAO    ch: = make (chan int)    go func () {        ch <-do_stuff (x)    } ()    return ch}func fanin (CHS ... chan int) chan  int {    ch: = make (chan int)    for _, c: = Range CHS {        //note here explicitly value        go func (c chan int) {ch <-<-C} (c) Compound    }    return Ch}func main () {    Result: = Fanin (Branch (1), Branch (2), Branch (3)) for    I: = 0; i < 3 ; i++ {        FMT. Println (<-result)    }}

Select Monitoring Channel

Go has a statement called select , which monitors the flow of data across channels.

The following program is a use example of SELECT, we monitor three channels of data outflow and collect data into one channel.

func foo (i int) Chan int {    c: = make (chan int)    go func () {C <-i} ()    return C}func main () {    C1, c2, C 3: = foo (1), Foo (2), Foo (3)    c: = make (chan int)    go func () {//Open a goroutine monitor each channel data output and collect data to channel C for        {            Selec t {//monitor C1, C2, C3 outflow, and all incoming channels C case            v1: = <-c1:c <-v1 Case            v2: = <-c2:c <-v2 case            v3: = &L t;-c3:c <-v3            }}}    ()    //block mainline, remove the data for Channel C for    I: = 0; i < 3; i++ {        fmt. PRINTLN (<-C)//from print to see our data output is not strictly in the order of the}    }

With SELECT, our functions in the example code in the multiplexing fanIn can be written in this way (so that you don't have to open a few goroutine to fetch the data):

Func fanin (Branches ... chan int) chan int {    c: = make (chan int)    go func () {for        I: = 0; i < len (branch ES); i++ {//select will attempt to fetch data from each channel in turn            select {Case            v1: = <-branches[i]: C <-v1            }}    ()    Return C}

When using SELECT, sometimes time-outs are required, where the timeout channel is quite interesting:

Timeout: = time. After (1 * time. Second)//timeout is a timing channel, if time is reached, a signal will be sent out for is_timeout: = false;!is_timeout; {    Select {///monitor channel C1, C2, C3, timeout channel data outflow case    v1: = <-c1:fmt. Printf ("received%d from C1", v1) Case    v2: = <-c2:fmt. Printf ("received%d from C2", v2) case    v3: = <-c3:fmt. Printf ("Received%d from C3", V3) case    <-timeout:is_timeout = TRUE//timeout    }}

End Flag

In go concurrency with parallel notes one of the most important and common applications we've talked about is the use of unbuffered channels to block the main line and wait for the goroutine to end.

So we don't have to use timeout again.

Then update the scheme for the above timeout to end the main line:

Func Main () {    c, quit: = make (chan int), make (chan int)    go func () {        C <-2  //Add Data        quit <-1// Send Complete Signal    } () for    is_quit: = false;!is_quit; {        Select {///monitor channel C data outflow case        V: = <-c:fmt. Printf ("received%d from C", v) case        <-quit:is_quit = TRUE//Quit channel has output, Close for Loop        }}    }

Daisy Chain

Simply put, the data flows from one end to the other, looking like a linked list, and wondering why you should take such an awkward name.

The English name of the daisy chain is called: Daisy-chain, one of its applications is to make filters, for example, we can sift under 100 prime number (you need to know what is the Sieve method first)

The program has a detailed comment, no longer explained.

/* * Using Channel daisy-chain sieve method to find the prime number of an integer range * Sieve method to find the prime number of the basic idea is: to start from 1, a range of positive integers from small to large order, * 1 is not a prime, first sieve it off. The remainder of the number selected is the prime number, and then the multiplier is removed.    * And so on, until the sieve is empty when the end */package Mainimport "FMT" func xrange () Chan int{//starting from 2 the integer generator var ch chan int = make (chan int) Go func () {//Open a goroutine for i: = 2;; i++ {ch <-I//until channel request data, only add I into Channel}} () re    Turn Ch}func filter (in Chan int, number int) Chan int {///Enter an integer queue, sift out a multiple of number, not a multiple of number into the output queue//in: Input queue                Out: = Make (chan int) go func () {for {i: = <-in//from input take an if I% number! = 0 { Out <-I//Put output Channel}}} () return Out}func main () {const MAX = 100//Find out within 100 There are primes nums: = xrange ()//Initialize an integer generator number: = <-nums//Catch an integer from the generator (2) as the initialization integer for number <= max {//Numbe R as a sieve, when the sieve exceeds Max, the filter fmt ends. PRINTLN (number)//print prime, sieve is a prime number nums = Filter (nums, number)//sieve out number multiples of number = <-nums//Update Sieve} }

Random number generator

The channel can be used as a generator, and as a special example, it can also be used as a random number generator. Here is a random 01 generator:

Func rand01 () chan int {    ch: = make (chan int)    go func () {        for {            Select {//select will attempt to execute each case, if all can be executed, then with Machine Select an execution case            CH <-0: Case            ch <-1:            }        }    } ()    return Ch}func main () {    Generator: = Rand0 1 ()//Initialize a 01 random generator    //test, Print 10 random for    I: = 0; i < i++ {        FMT. Println (<-generator)    }}

Timer

We have just actually contacted the channel as a timer, time in the bag After will make a timer.

Take a look at our timers!

/* * Use Channel to do timer */package Mainimport (    "FMT"    "Time") Func Timer (duration time. Duration) chan bool {    ch: = Make (chan bool)    go func () {Time        . Sleep (duration)        ch <-true//to TIME!    } ()    return Ch}func main () {    timeout: = Timer (time. Second)//timer 1s for    {        Select {case        <-timeout:            fmt. Println ("Already 1s!")//To TIME            return  //End Program}}    }

Todo

Examples of Google's application scenarios.

This article mainly summarizes the use of channel, goroutine some design patterns.

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.