Golang Funny:play with Channel

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

Golang has a funny toy:channel. Here have some words from the specification:

A channel provides a mechanism for the concurrently executing functions to synchronize execution and communicate by Passin G A value of a specified element type.

yep! It is boring and dull. You can ' t understand it when you read it first time. Actually, you can think of it as a PIPE or a FIFO queue. It ' s lightweight and simple. Channel is not of Golang origin. It also appears in some other languages (embedded). And most of time, it's a function as a part of a huge, complexly and heavy message queue system.

Ok! Let ' s has some fun.

Common Way:producer/consumer

The most common-from-use channel. A producer makes things and put them into the channel. and a consumer get them from the channel. On to, in order. If the channel is full, the producer must wait. Otherwise, if the channel is empty, the consumer must wait.

You can get full source from here. Running it at the local is better.

Producer:

Func producer (c Chan int64, Max int) {    defer close (c) for    i:= 0; i < max; I + + {        c <-time. Now (). Unix ()    }}

The producer makes a number of ' Max ' int64, and put them into the channel ' C '. Notice that, here's a defer for closing the channel.

Consumer:

Func consumer (c Chan Int64) {    var v int64    OK: = True    for OK {        if V, ok = <-c; OK {            FMT. Println (v)        }}}    

Read int64s from the Channel One by one, and print them on to the screen. When the channel closed, the variable ' OK ' is set to ' false '.

Auto-increment ID Generator

If We let the producer makes a sequence of integer. It'll be a auto-increment ID generator. I wrote a package that encapsulates it. You can found it in here. The usage can is found at here.

Type AUTOINC struct {    start, step int    queue Chan int    running Bool}func New (start, step int) (AI *autoinc) {
  ai = &autoinc{        start:start,        step:step,        running:true,        queue:make (chan int, 4),    }    Go Ai.process ()    return}func (AI *autoinc) process () {    defer func () {Recover ()} () for    i: = Ai.start; ai.running; I=i+ai.step {        ai.queue <-i    }}func (ai *autoinc) Id () int {    return <-ai.queue}func (AI *autoinc) Clos E () {    ai.running = False    Close (ai.queue)}

Semaphore

Semaphore is a funny usage of Channel. Here's a demo from "Effective Go". Do should have read it, haven ' t? If not, read it now ...

I have used the channel as a semaphore in the Gearman-go, a package for Gearman job server. You can found the codes here. Line 232, the worker.exec is blocked by Worker.limit.

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 Finis H.    }}

Randomized sequence

Of course, we could modify the Auto-increment ID generator. Let the producer makes randomized number and put into the channel. But, it's not funny enough. Right?

Here is another randomized sequence. It was inspired by the specification. It produces 0 or 1 randomly:

Func producer (c Chan int64, Max int) {    defer close (c) for    i:= 0; i < max; I + + {        Select {//Randomized SEL ECT case            C <-0: Case            C <-1:        }    }}

The timeout timer

If A channel is blocked at Read/write, it'll be blocked forever. Until the channel was closed and then a panic raised. The channel has no timeout for timer build in. And it looks like there are no plan to add a timer into channel. But the most of time, we need a timeout mechanism. Eg. A producer executed, and something wrong with it, then nothing put into the channel. The consumer is blocked now and until the channel was closed. Close the channel for every time? No! That's not a good idea.

Here is a solution.

    c: = Make (chan int64, 5)    defer close (c)    timeout: = Make (chan bool)    defer close (timeout)    go func () {        T Ime. Sleep (time. Second)//Wait a Second        timeout <-true//put a bool value into the Channel    } ()    Select {Case        <-ti Meout://timeout            FMT. PRINTLN ("Timeout ...") Case        <-c://received a data            FMT. Println ("Read a data.")    }

Have you noticed the SELECT statement? Which channel receive data, which sub-branch execution. So ... do we need more explanation?

This also used in the client of Gearman-go, line 238.

further: Thx @mjq. The time. After is really better solution. and I read the source codes at Src/pkg/time/sleep.go, line 74. Internal implementation is same as the above.

One more thing

This isn't only a introduction on Golang channel, but also a 中文版 writing exercise. So, if you had some other ideas about Golang channel usage, share them with me! If you found some issues in my blog, the plz point is out of them for me. Thx!

[2012.06.26] updated!
Using close to broadcast

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.