3 Elegant Go Channel usage

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

The guy who wrote go should have heard the words of Rob Pike.

Do not communicate by sharing memory; Instead, share memory bycommunicating.

I believe that many friends and I, in the actual application of the total sense of no benefit, in order to use the channel. But in my experience, this is the code when the scene is not complicated, the channel is not familiar with the result, so I hope this article can bring you a new idea, the Golang elegant channel has a deeper understanding:

Fan In/out

The output of the data sometimes needs to be fan-out/In (Fanin/out), but in the function calls often have to modify the interface, and the upstream and downstream of the data is very dependent on the very high, so the general use of channel Fanin/out, so you can easily achieve similar to the shell of the pipeline.

func fanIn(input1, input2 <-chan string) <-chan string {   c := make(chan string)   go func() {       for {           select {           case s := <-input1:  c <- s           case s := <-input2:  c <- s           }       }   }()   return c}

Sync Goroutine

Two goroutine synchronization states, such as a goroutine need to let B goroutine exit, the general practice is as follows:

func main() {   g = make(chan int)   quit = make(chan bool)   go B()   for i := 0; i < 3; i++ {       g <- i   }   quit <- true // 没办法等待B的退出只能Sleep   fmt.Println("Main quit")}func B() {   for {       select {       case i := <-g:           fmt.Println(i + 1)       case <-quit:           fmt.Println("B quit")           return       }   }}/*Output:123Main quit*/

But the main function is not able to wait for B to exit properly, so B quit no way to print, the program directly exited. However, Chan is the first object in go, so you can pass Chan into Chan, so the above code can define quit as Chan Chanbool, which controls the synchronization of two Goroutine

func main() {   g = make(chan int)   quit = make(chan chan bool)   go B()   for i := 0; i < 5; i++ {       g <- i   }   wait := make(chan bool)   quit <- wait   <-wait //这样就可以等待B的退出了   fmt.Println("Main Quit")}func B() {   for {       select {       case i := <-g:           fmt.Println(i + 1)       case c := <-quit:           c <- true           fmt.Println("B Quit")           return       }   }}/* Output123B QuitMain Quit*/

Distributed recursive invocation

In real life, what would you do if you wanted to talk to the President of the United States? The first step is to call your friends in the United States, and then they will start their own networks, find people who might know the President of the United States, and so on until they find it. This is also the same in the Kadmelia distributed system, if you need to get the target ID information, then keep querying, the query node even if there is no relevant information, it will return to the nearest node, until the ID or wait for the timeout. Well, how do you do this with go?

Func Recursivecall (CTX context. Context, id []byte, initialnodes []*node] {seen: = map[string]*node{}///Seen node record request: = Make (chan *node, 3)//Set    Request node channel//Input initial node go func () {for _, N: = range Initialnodes {request <-n} } () Out:for {//loop until the data is found if the DataSource = nil {return}//In the new request, timeout and on Layer Cancel request in select Select {case N: = <-request:go func () {//Send new please Request Response: = S.sendquery (CTX, N, methodfindvalue, id) Select {case <-ctx . Done (): Case msg: =<-response:seen[responsetonode (response)] = N//More Newly seen node information//Load new node for _, RN: = Range Loadnodeinfof Rombyte (Msg[payloadstart:]) {mu. Lock () _, OK: = Seen[rn. HexID ()] Mu.                                 Unlock ()//have seen, skip this node if OK {                                                        Continue} AddNode (RN)                    The new node is fed into channel request <-RN} }}} () Case <-time. After ($ * time.millisecond): Break out//break to outer layer, otherwise just jump to the outside of the loop case <-ctx. Done (): Break Out}} return}

At this point the Bufferedchannel is similar to a local queue, processing the required nodes, but the subtlety of this code is that the block operation here is select and can be canceled at any time, rather than waiting or knowing the length of the queue.

What questions do you have about the use of these three channel types, welcome to discuss ╮(╯▽╰)╭

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.