Learn more about golang (2)-Channel

Source: Internet
Author: User
Tags variable scope
Channel1. Overview

"Network, concurrency" is the two major feature of the Go language. The Go language is known as the "Internet C language". Compared with the traditional C language, writing a server uses less and simpler code. Writing a server is concurrent in addition to the network. Compared with other languages such as Python, go supports concurrency to improve its performance.

Goroutine and channel are two core feature of go in terms of "concurrency.

 

A channel is a way of communication between goroutines. It is similar to a Unix pipeline.

Channel declaration:

Channeltype = ("Chan" | "Chan" "<-" | "<-" "Chan") elementtype.

 

For example:

VaR ch Chan int

VaR mongochan <-int // the token can only be written.

VaR CH2 <-chan int // CH2 can only be read

 

Channel is type-related, that is, a channel can only pass one type. For example, the above ch can only pass Int.

 

In the go language, there are four reference types: slice, MAP, channel, and interface.

Slice, map, and channel are generally initialized through make:

CI: = make (Chan INT) // unbuffered channel of Integers

CJ: = make (Chan int, 0) // unbuffered channel of Integers

CS: = make (chan * OS. File, 100) // buffered channel of pointers to files

When creating a channel, you can provide an optional integer parameter to set the buffer size of the channel. The default value is 0, which is used to build the default "no buffer channel", also known as "synchronous channel ".

 

As a communication mechanism between goroutine, channel is similar to other communication mechanisms in the operating system. It generally has two purposes: synchronization or message transmission.

 

2. Synchronization

C: = make (Chan INT) // allocate a channel.

// Start the sort in a goroutine; when it completes, signal on the channel.

Go func (){

List. Sort ()

C <-1 // send a signal; value does not matter.

}()

Dosomethingforawhile ()

<-C // wait for sort to finish; discard sent value.

In the preceding example, the sub-goroutine is used for sorting. The main goroutine can do some other tasks and then wait for the sub-goroutine to complete sorting.

 

The receiver is blocked until data arrives. If the channel is unbuffered, the sender will be blocked until the receiver extracts the data. If the channel has a buffer, the sender will be blocked until the data is copied to the buffer. If the buffer is full, the sender can recover from the blocking status only after the receiver takes the data.

 

3. message transmission

Let's simulate the classic producer-consumer model.

Func producer (queue Chan <-int ){

For I: = 0; I <10; I ++ {

Queue <-I

}

}

 

Func consumer (queue <-chan INT ){

For I: = 0; I <10; I ++ {

V: = <-queue

FMT. println ("receive:", V)

}

}

 

Func main (){

Queue: = make (Chan int, 1)

Go producer (Queue)

Go consumer (Queue)

Time. Sleep (1e9) // Let the producer and consumer complete

}

The preceding example generates data in the producer and processes the data in the consumer.

 

4. Server programming model

Programming on the server is a common model: the main thread receives requests, and then distributes the requests to the working thread to complete request processing. Use go as follows:

Func handle (R * request ){

Process (r) // may take a long time.

}

 

Func serve (queue chan * request ){

For {

Req: = <-queue

Go handle (req) // don't wait for handle to finish.

}

}

 

Generally, the processing capability of the server is not infinite. Therefore, it is necessary to limit the number of threads (or goroutine. In C/C ++ programming, we generally use semaphores. In go, we can achieve the same effect through channel:

VaR SEM = make (Chan int, maxoutstanding)

 

Func handle (R * request ){

SEM <-1 // wait for active queue to drain.

Process (r) // may take a long time.

<-SEM // done; Enable next request to run.

}

 

Func serve (queue chan * request ){

For {

Req: = <-queue

Go handle (req) // don't wait for handle to finish.

}

}

By introducing the SEM channel, We have restricted running of only maxoutstanding goroutine at the same time. However, the above practice only limits the number of running goroutines, and does not limit the number of goroutines generated. If the request arrives too quickly, a large number of goroutines will be generated, which will completely consume system resources.

Therefore, it is necessary to limit the number of goroutine instances:

Func serve (queue chan * request ){

For Req: = range queue {

SEM <-1

Go func (){

Process (req) // buggy; see explanation below.

<-SEM

}()

}

}

The above Code seems simple and clear, but there is a problem in go. Loop variables in the go language are reused in each iteration. More directly, req is shared among all sub-goroutine. From the perspective of variable scope, the variable req is global for all goroutines.

This problem falls into the scope of language implementation. In C, you should not pass a local variable to another thread for processing. There are many solutions, which are discussed here. Personally, I prefer the following method:

Func serve (queue chan * request ){

For Req: = range queue {

SEM <-1

Go func (R * request ){

Process (r)

<-SEM

} (Req)

}

}

At least, such code won't confuse beginners of a go program. In addition, it is more common sense from the perspective of variable scope.

 

In actual C/C ++ programming, we tend to create working threads at the beginning, and the number of threads is fixed. In go, we can also do this:

Func handle (queue chan * request ){

For R: = range queue {

Process (r)

}

}

 

Func serve (clientrequests chan * request, quit Chan bool ){

// Start handlers

For I: = 0; I <maxoutstanding; I ++ {

Go handle (clientrequests)

}

<-Quit // wait to be told to exit.

}

Start a fixed number of handle goroutine at the beginning, and each goroutine directly reads requests from the channel. This method is relatively simple, but I don't know if there is a problem with "surprise group? The goroutine implementation needs to be analyzed in the future.

 

5. Channel passing the channel

As a native type of the Go language, channel can naturally be passed through the channel. Channel Transmission allows you to easily solve some practical problems.

In the previous section, the main goroutine transmits requests to the working goroutine through a channel. Similarly, we can return the processing result to the primary goroutine through the channel.

Main goroutine:

Type request struct {

ARGs [] int

Resultchan Chan int

}

 

Request: = & request {[] int {3, 4, 5}, make (Chan INT )}

// Send request

Clientrequests <-Request

// Wait for response.

FMT. printf ("Answer: % d \ n", <-request. resultchan)

The main goroutine sends the request to the request channel and waits for the result channel. After processing the sub-goroutine, write the result to the result channel.

Func handle (queue chan * request ){

For Req: = range queue {

Result: = do_something ()

Req. resultchan <-Result

}

}

 

6. Multiple Channels

In actual programming, it is often possible to process multiple channels in a goroutine. It is impossible for us to block the two channels. In this case, we should select the field. Similar to the SELECT statement in C language that can monitor multiple FD, select statements in go language can wait for multiple channels.

C1: = make (Chan string)

C2: = make (Chan string)

 

Go func (){

Time. Sleep (time. Second * 1)

C1 <-"one"

}()

Go func (){

Time. Sleep (time. Second * 2)

C2 <-"two"

}()

 

For I: = 0; I <2; I ++ {

Select {

Case msg1: = <-C1:

FMT. println ("received", msg1)

Case msg2: = <-C2:

FMT. println ("received", msg2)

}

}

In C, we usually pass a time-out time to the select function. In go, select does not have this parameter, which is equivalent to a time-out value of 0.

 

References

Https://golang.org/doc/effective_go.html


YY brother
Source: http://www.cnblogs.com/hustcat/
The copyright of this article is shared by the author and the blog Park. You are welcome to repost this article. However, you must retain this statement without the author's consent and provide a clear link to the original article on the article page. Otherwise, you will be held legally liable.

Learn more about golang (2)-Channel

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.