Skip to content

Instantly share code, notes, and snippets.

@kmlx
Forked from kachayev/concurrency-in-go.md
Created March 12, 2016 10:54
Show Gist options
  • Select an option

  • Save kmlx/d06eb118d3d2d8fa1ebd to your computer and use it in GitHub Desktop.

Select an option

Save kmlx/d06eb118d3d2d8fa1ebd to your computer and use it in GitHub Desktop.

Revisions

  1. @kachayev kachayev revised this gist Sep 15, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -162,7 +162,7 @@ It can take a long time to get current weather, i.e. when you have long list of
    func collect(state string) Weather {
    calc, ok := calculations.get(state) // check if it's in progress
    if !ok {
    calc.calculations.run(state) // run otherwise
    calc = calculations.run(state) // run otherwise
    }
    return calc.Wait() // wait until done
    }
  2. @kachayev kachayev revised this gist Sep 14, 2014. 1 changed file with 22 additions and 20 deletions.
    42 changes: 22 additions & 20 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,8 @@ Go was designed for building concurrency applications easily so it has goroutine

    ![channels](https://pbs.twimg.com/media/BvBSJJQCAAAWH8e.jpg)

    Keynote: **99% of time I don't really care if the response is delivered with a channel or a magical unicorn brought it on its horn.**

    It’s so cool to find yourself writing tutorial for beginners! And it's a bit painful when you are trying to implement big and sophisticated system(s). Channels are [primitives](https://golang.org/doc/). They are low-level building blocks and I highly doubt you want to work with them on daily basis.

    Look at ["advanced patterns"](http://blog.golang.org/advanced-go-concurrency-patterns) and ["pipeline"](http://blog.golang.org/pipelines). Not that simple right? Too many things to keep in mind and constantly memorize: when and how to close channels, how to propagate errors, how to free resources. I'm complaining about this not because I've tried implementing something and failed. But because I work with stuff like this every single day.
    @@ -266,7 +268,7 @@ You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` o

    ### Pub/sub

    Assume that we want to build real-time service. So now our client can open websocket connection with `q=CA` request and gets instant updates about weather changes in California. Usually it will look like:
    Assume that we want to build real-time service. So now our client can open websocket connection with a `q=CA` request and get instant updates about weather changes in California. It would look something like:

    ```go
    // deliverer
    @@ -341,13 +343,13 @@ Which means that I can reuse the same code for channels and futures. You may als
    ;; note, that it will close all channels (including implicit intermediate one) properly
    ```

    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably, not. In this case why I'm allowed to do `make(chan int)` and not allowed to do `make(Future int)`?
    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably not. In this case why am I allowed to do `make(chan int)` and not `make(Future int)`?

    ### Request/Reply

    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.
    Assume that our users like our service and use it actively. So we decided to introduce a simple API limitation: number of requests for each IP, per day. It's simply to collect the number of calls into single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, sounds like a nice idea.

    So for the first we need goroutine that will be responsible for collecting number of requests.
    So for the first we need the goroutine that will be responsible for collecting number of requests.

    ```go
    req := make(chan string)
    @@ -371,7 +373,7 @@ go func() {
    }()
    ```

    It's easy. Now can calculate number of requests for each IP. Not that much... We also have to be able to ask permissions to execute request.
    It's easy. Now can calculate number of requests for each IP. Not that much... We also have to be able to ask permission to execute request.

    ```go
    type Req struct {
    @@ -410,58 +412,58 @@ go func() {
    }()
    ```

    I don't even try to ask you about generic solution (without hardcoded strings and ints). I ask you to check if everything right with this code? Is it that simple?
    I won't even try to ask you about generic solution (without hardcoded strings and ints). I ask you instead, to check if everything is right with this code? Is it that simple?

    Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I don't want everybody to wait for slow clients. Yes? And what if I have too many slow clients? Maybe I have to handle this somehow.
    Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I don't want anybody to wait for slow clients. Yes? And what if I have too many slow clients? Maybe I have to handle this somehow.

    Is this part `requests <- r` that simple? What if my actor (server) is too busy to reply now? Maybe I need to handle timeouts here...

    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to hold requests until initialization is finished.
    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And the ability to hold requests until initialization is finished.

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate. 98% of time I don't want to see this `resp: make(chan int, ?)` and I really don't want to think what should I put instead of `?`.

    **99% of time I don't really care if response is delivered with a channel or a magical unicorn brought it on its horn.**
    **99% of time I don't really care if the response is delivered with a channel or a magical unicorn brought it on its horn.**

    ### And counting

    There are many other common concurrency situations. I think you've already got the idea.
    There are many other common concurrency situations. I think you've already gotten the idea.

    ## The Pain

    You can tell me, that described patterns are not common. But.. I have to implement almost all of them in all my projects. Every. Single. Time. Maybe I’m just out of luck and you projects are that simple as tutorial for beginners.
    You can tell me, that described patterns are not common. But.. I have to implement almost all of them in all my projects. Every. Single. Time. Maybe I’m just out of luck and your projects are as simple as tutorial for beginners.

    I know that most of you will tell "world is too hard and programming is too painful". I hasten to upset you: there are at least few examples of languages that solved this problem at least partially. Or at least working on solving it. Haskell and Scala type systems give you ability to build strong [high-level abstractions][haskell-book] or even custom [control flows][oz-style] to [deal](https://github.com/scala/async) with concurrency. As an opposite Clojure is dynamically typed that encourage you to distil and share [high level][clojure-async] [abstraction][clojure-trans].
    I know that most of you will say "world is too hard and programming is too painful". I continue to upset you: there are at least a few examples of languages that solved this problem at least partially. Or at least working on solving it. Haskell and Scala type systems give you ability to build strong [high-level abstractions][haskell-book] or even custom [control flows][oz-style] to [deal](https://github.com/scala/async) with concurrency. An opposite Clojure is dynamically typed that encourage you to distil and share [high level][clojure-async] [abstraction][clojure-trans]. Rust has [channels](http://doc.rust-lang.org/std/comm/) and [generics](http://doc.rust-lang.org/rust.html#generic-functions).

    Make it works -> Make it beautiful -> Make it reusable.

    First step is done. What's next? Don't get me wrong, go is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?
    Now that the first step is done. What's next? Don't get me wrong, `go` is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?


    ## P.S. Building Twitter Analyzer

    About real-world pipelining.

    Probably you've already seen [Twitter Analytics](https://analytics.twitter.com/) which is really great. Assume for the second that it's not introduced yet and we have to run our own analysis: for given username calculate how many unique users saw (at least theoretically) each of his own tweet. How we can do this? Not that hard: read user's timeline, filter away all retweets and replies, for all other tweets ask for all retweeters, for each retweeter ask for list of followers, merge all retweeters' followers together and add own user's followers. What I want to have as a result of these steps: `map[TweetId][]Username` (retweeters) and `map[Username][]Username`. It would be enough to build fancy table to show to requester.
    Probably you've already seen [Twitter Analytics](https://analytics.twitter.com/) which is really great. Assume for the time being, that it's not introduced yet and we have to run our own analysis: for a given username calculate how many unique users saw (at least theoretically) each of his own tweets. How we can do this? Not that hard really: read user's timeline, filter away all retweets and replies, for all other tweets ask for all retweeters, for each retweeter ask for a list of followers, merge all retweeters' followers together and add own user's followers. What I want to have as a result of these steps: `map[TweetId][]Username` (retweeters) and `map[Username][]Username`. It would be enough to build a fancy table to show to the requester.

    Few technical details that you should be aware of:

    - Twitter API requires OAuth for each call and set strong limitations (450 calls per 15 minutes per each user). To deal with such limitation we're going to use predefined list of OAuth tokens (i.e. 50) organized into pool of workers where each worker is able to suspend himself before facing problems with limits.
    - Twitter API requires OAuth for each call and sets strong limitations (450 calls per 15 minutes per each user). To deal with such a limitation, we're going to use a predefined list of OAuth tokens (i.e. 50) organized into a pool of workers where each worker is able to suspend himself before facing problems with limits.

    - Most Twitter API calls use pagination for results with `since_id` or `max_id` continuations. So you can't rely on that fact that single call to worker will return you full result.
    - Most Twitter API calls use pagination for results with `since_id` or `max_id` continuations. So you can't rely on the fact that single call to worker will give you full result.

    [Example of rough implementation](https://gist.github.com/kachayev/50d89615101444cd62ad). Note, that there is no need for you to understand everything in this file. Just the opposite. If you can't understand it after quick screening then we're on the right way.
    [Example of rough implementation](https://gist.github.com/kachayev/50d89615101444cd62ad). Note, that there is no need for you to understand everything in this file. Just the opposite. If you can't understand it after quick screening then we're on the right path.

    So what do we have here?

    1. Few stages of computations: `TimelineReader` -> `RetweetersReader` -> `FollowersReader` -> `FinalReducer`.

    2. Self-stage messaging. All stages are recursive cause of pagination. It means that each stage emits messages both to next stage and to itself. It's much harder to deal with cancellation in this case. Or even find out when everything is done on single stage.
    2. Self-stage messaging. All stages are a recursive cause of pagination. It means that each stage emits messages both to the next stage and to itself. It's much harder to deal with cancellations in this case. Or even find out when everything is done on a single stage.

    3. Early propagation. There are at least 2 cases here: for the first in order to collect mapping from `TweetId` to `[]Username` we need to send collected info directly from `RetweetersReader` to `FinalReducer`; for the second we know from very beginning that we need to fetch followers for initial user, so his username should be emitted to `RetweetersReader` bypassing `TimelineReader` stage.
    3. Early propagation. There are at least 2 cases here: for the first in order to collect mapping from `TweetId` to `[]Username` we need to send collected info directly from `RetweetersReader` to `FinalReducer`; for the second we know from the very beginning that we need to fetch followers for the initial user, so his username should be emitted to `RetweetersReader` bypassing `TimelineReader` stage.

    4. Middleware reducers. `FollowersReader` is not only a pipe. It's a reducer for usernames that we've already seen (cause you don't want to duplicate you work).
    4. Middleware reducers. `FollowersReader` is not only a pipe. It's a reducer for usernames that we've already seen (cause you don't want to duplicate your work).

    5. Long running workers. You can't just wait for workers shutdown in many cases, i.e. when you're implementing a server that should respond to many clients simultaneously.

  3. @kachayev kachayev revised this gist Sep 14, 2014. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -133,7 +133,7 @@ Content-Type: application/json; charset=utf-8

    ### Pmap

    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We've talked about such pattern already. It's `pmap`. And I want my code to look like
    Let's start from something that we already know. So, we've got the request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal `go` representation for lazy sequence). Next? For each city we have to call OpenWeatherMap API and collect results into single `map[City]Weather`. We've talked about such pattern already. It's `pmap`. And I want my code to look like

    ```go
    chanCities := findCities(state)
    @@ -170,13 +170,13 @@ This is so called [future/promise](http://en.wikipedia.org/wiki/Futures_and_prom

    > They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
    I heard few times from different people that go `future` is a simple:
    I've heard from a number of people that `go` `future` is a simple:

    ```go
    f := make(chan int, 1)
    ```

    Which is wrong cause all waiters should get result. And this version is also wrong:
    Which is wrong because all waiters should get result. And this version is also wrong:

    ```go
    f := make(chan int, 1)
    @@ -185,7 +185,7 @@ f <- v
    // use v here
    ```

    Because it's impossible to manage resources this way. And I wish you good luck to find the bug if somebody missed `f <- v` part in his code.
    Because it's impossible to manage resources this way. And I wish you luck finding a bug if somebody missed the `f <- v` part in his code.

    It's not that hard though to implement `promise` directly storing all waiters (I'm not sure that this code is really bugs free):

    @@ -237,7 +237,7 @@ go func(){
    p.Value().(int) // blocks and returns interface{} when ready
    ```

    But `interface{}` and type casting are already here. What do I really want here?
    But `interface{}` and type casting are already here. What do I really want?

    ```go
    // .. somewhere in well-tested library or even in stdlib
    @@ -260,9 +260,9 @@ go func(){
    v.Value() // blocks and returns 42, not interface{}
    ```

    No, sure, nobody needs generics. What the hell I'm talking about?
    No, sure, nobody needs generics. What the hell am I talking about?

    You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` operations in single goroutine. You can also introduce special `.ValueWithTimeout` method which will be really helpful for end users. And there're lots of other "you can...". Despite the fact that we're talking about 20 lines of code (that probably will grow each time you discovered more details of futures/promises interactions). Do I really need to know (or even think) about channels that delivered me the value? No.
    You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` operations in a single goroutine. You can also introduce special `.ValueWithTimeout` method which will be really helpful for end users. And there're lots of other "you can...". Despite the fact that we're talking about 20 lines of code (that probably will grow each time you discover more details of futures/promises interactions). Do I really need to know (or even think) about channels that delivered me the value? No.

    ### Pub/sub

  4. @kachayev kachayev revised this gist Sep 14, 2014. 1 changed file with 446 additions and 1 deletion.
    447 changes: 446 additions & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -34,4 +34,449 @@ At [Kyiv Go Meetup][go-meetup] I experienced the same situation: 20 lines of cle

    Ok. Let’s try to collect such patterns. From work experience, from books, from other languages (yeah, guys, I know that it's hard to believe but there are several other languages also designed for concurrency).

    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about the network of channels
    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about the network of channels. Not about your application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).

    ```go
    func merge(cs ...<-chan int) <-chan int {
    var wg sync.WaitGroup
    out := make(chan int)

    // Start an output goroutine for each input channel in cs. output
    // copies values from c to out until c is closed, then calls wg.Done.
    output := func(c <-chan int) {
    for n := range c {
    out <- n
    }
    wg.Done()
    }
    wg.Add(len(cs))
    for _, c := range cs {
    go output(c)
    }

    // Start a goroutine to close out once all the output goroutines are
    // done. This must start after the wg.Add call.
    go func() {
    wg.Wait()
    close(out)
    }()
    return out
    }
    ```

    Hm... `<-chan int`. Not that abstract to reuse in my own application (i.e. move to library)... And not that obvious to reimplement each time when I need it. How to make it reusable? `<-chan interface{}`? Welcome to the land of types casting and runtime panics. If you want to implement high level fan-in (merge) you’re losing type safety. The same (unfortunately) goes for all other patterns.

    What I really want here is:

    ```go
    func merge[T](cs ...<-chan T) <-chan T
    ```

    Yeah, I know that Go [doesn't have generics](http://golang.org/doc/faq#generics) because who ever need them?

    ## What is the Weather Now?

    Return to patterns. Let’s analyse hypothetical project that’s really close to practical experience in server-side development. We need a server that accepts request about weather for a given USA state and respond with info collected from [OpenWeatherMap](http://openweathermap.org/api). In such a way:

    ```shell
    $ http localhost:4912/weather?q=CA
    HTTP/1.1 200 OK
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Methods: GET, POST
    Access-Control-Allow-Origin: *
    Connection: keep-alive
    Content-Type: application/json; charset=utf-8
    ```

    ```json

    [{
    "clouds": {
    "all": 40
    },
    "id": 5391959,
    "main": {
    "temp": 288.89,
    "temp_max": 291.48,
    "temp_min": 286.15
    },
    "name": "San Francisco",
    "weather": [
    {
    "description": "mist",
    "icon": "50d",
    "id": 701,
    "main": "Mist"
    }
    ]
    }, {
    "clouds": {
    "all": 90
    },
    "id": 5368361,
    "main": {
    "temp": 292.83,
    "temp_max": 296.15,
    "temp_min": 289.15
    },
    "name": "Los Angeles",
    "weather": [
    {
    "description": "mist",
    "icon": "50d",
    "id": 701,
    "main": "Mist"
    }
    ]
    }]
    ```

    ### Pmap

    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We've talked about such pattern already. It's `pmap`. And I want my code to look like

    ```go
    chanCities := findCities(state)
    resolver := func(name City) Weather { return openWeatherMap.AskFor(name) }
    weather := chanCities.Par.Map(resolver)
    ```

    or in case of bounded parallelism

    ```go
    chanCities := findCities(state)
    pool := NewWorkers(20)
    resolver := func(w Worker, name City) Weather { return w.AskFor(name) }
    weather := chanCities.Par.BoundedMap(pool, resolver)
    ```

    That's it. I want all this `<-done` synchronizations and `select` sacramentals to be entire hidden.

    ### Futures & Promises

    It can take a long time to get current weather, i.e. when you have long list of cities for concrete state. Off course you don't want to duplicate API calls so you should manage simultaneous requests somehow:

    ```go
    func collect(state string) Weather {
    calc, ok := calculations.get(state) // check if it's in progress
    if !ok {
    calc.calculations.run(state) // run otherwise
    }
    return calc.Wait() // wait until done
    }
    ```

    This is so called [future/promise](http://en.wikipedia.org/wiki/Futures_and_promises). From Wiki:

    > They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
    I heard few times from different people that go `future` is a simple:

    ```go
    f := make(chan int, 1)
    ```

    Which is wrong cause all waiters should get result. And this version is also wrong:

    ```go
    f := make(chan int, 1)
    v <- f
    f <- v
    // use v here
    ```

    Because it's impossible to manage resources this way. And I wish you good luck to find the bug if somebody missed `f <- v` part in his code.

    It's not that hard though to implement `promise` directly storing all waiters (I'm not sure that this code is really bugs free):

    ```go
    type PromiseDelivery chan interface{}
    type Promise struct {
    sync.RWMutex
    value interface{}
    waiters []PromiseDelivery
    }

    func (p *Promise) Deliver(value interface{}) {
    p.Lock()
    defer p.Unlock()
    p.value = value
    for _, w := range p.waiters {
    locW := w
    go func(){
    locW <- value
    }()
    }
    }

    func (p *Promise) Value() interface{} {
    if p.value != nil {
    return p.value
    }

    delivery := make(PromiseDelivery)
    p.waiters = append(p.waiters, delivery)
    return <-delivery
    }

    func NewPromise() *Promise {
    return &Promise{
    value: nil,
    waiters: []PromiseDelivery{},
    }
    }
    ```

    How to use it?

    ```go
    p := NewPromise()
    go func(){
    p.Deliver(42)
    }()
    p.Value().(int) // blocks and returns interface{} when ready
    ```

    But `interface{}` and type casting are already here. What do I really want here?

    ```go
    // .. somewhere in well-tested library or even in stdlib
    type PromiseDelivery[T] chan T
    type Promise[T] struct {
    sync.RWMutex
    value T
    waiters []PromiseDelivery[T]
    }
    func (p *Promise[T]) Deliver(value T)
    func (p *Promise[T]) Value() T
    func NewPromise[T]() *Promise[T]

    // in my code:
    v := NewPromise[int]()
    go func(){
    v.Deliver("woooow!") // compilation error
    v.Deliver(42)
    }()
    v.Value() // blocks and returns 42, not interface{}
    ```

    No, sure, nobody needs generics. What the hell I'm talking about?

    You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` operations in single goroutine. You can also introduce special `.ValueWithTimeout` method which will be really helpful for end users. And there're lots of other "you can...". Despite the fact that we're talking about 20 lines of code (that probably will grow each time you discovered more details of futures/promises interactions). Do I really need to know (or even think) about channels that delivered me the value? No.

    ### Pub/sub

    Assume that we want to build real-time service. So now our client can open websocket connection with `q=CA` request and gets instant updates about weather changes in California. Usually it will look like:

    ```go
    // deliverer
    calculation.WhenDone(func(state string, w Weather) {
    broker.Publish("CA", w)
    })

    // client
    ch := broker.Subscribe("CA")
    for update := range ch {
    w.Write(update.Serialize())
    }
    ```

    It's a typical pub/sub. You can learn about it from [Advanced Go Patterns](http://blog.golang.org/advanced-go-concurrency-patterns) talk and even find ready-to-use [implementations](https://github.com/tuxychandru/pubsub). The problems is that [they](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L34) [are](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L48) [all](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L54) [about](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L58) interfaces.

    Is it possible to implement:

    ```go
    broker := NewBroker[String, Weather]()
    // so that
    broker.Subs(42) // compilation failure
    // and
    broker.Subs("CA") // returns (chan Weather) not (chan interface{})
    ```

    Sure! If you're brave enough to copy-paste code from project to project with small fixes here and there.

    ### Map/filter

    Assume that we want to give our users more flexibility and we're introducing new query params: `show` which can be equal to `all|temp|wind|icon`.

    Probably you'll start from simples:

    ```go
    ch := broker.Subscribe("CA")
    for update := range ch {
    temps := []Temp
    for _, t := update.Temp {
    temps = append(temps, t)
    }

    w.Write(temps)
    }
    ```

    But after 10 such methods you'll realize that it's not composable and even boring. Maybe you need

    ```go
    ch := broker.Subscribe("CA").Map(func(w Weather) Temp { return w.Temp })
    for update := range ch {
    w.Write(update)
    }
    ```

    Wait, did I just say that channel is a [functor](http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)? As well as Future/Promise.

    ```go
    p := NewPromise().Map(func(w Weather) Temp { return w.Temp })
    go func(){
    p.Deliver(Weather{Temp{42}})
    }()
    p.Value().(Temp) // Temp, not Weather
    ```

    Which means that I can reuse the same code for channels and futures. You may also end up with something like [transducers](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming). I frequently use in ClojureScript code tricks like

    ```clojure
    (->> (send url) ;; returns chan, put single value to it {:status 200 :result 42} when ready
    (async/filter< #(= 200 (:status %))) ;; check that :status is 200
    (async/map< :result)) ;; expose only 42 to end user
    ;; note, that it will close all channels (including implicit intermediate one) properly
    ```

    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably, not. In this case why I'm allowed to do `make(chan int)` and not allowed to do `make(Future int)`?

    ### Request/Reply

    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.

    So for the first we need goroutine that will be responsible for collecting number of requests.

    ```go
    req := make(chan string)
    go func() { // wow, look here - it's an actor!
    m := map[string]int{}
    for r := range req {
    if v, ok := m[r]; !ok {
    m[r] = 1
    } else {
    m[r] = v + 1
    }
    }
    }()

    go func() {
    req <- "127.0.0.2"
    }()

    go func() {
    req <- "127.0.0.1"
    }()
    ```

    It's easy. Now can calculate number of requests for each IP. Not that much... We also have to be able to ask permissions to execute request.

    ```go
    type Req struct {
    ip string
    resp chan int
    }

    func NewRequest(ip string) *Req {
    return &Req{ip, make(chan int)}
    }

    requests := make(chan *Req)

    go func() {
    m := map[string]int{}
    for r := range requests {
    if v, ok := m[r.ip]; !ok {
    m[r.ip] = 1
    } else {
    m[r.ip] = v + 1
    }
    r.resp <- m[r.ip]
    }
    }()

    go func() {
    r := NewRequest("127.0.0.2")
    requests <- r
    fmt.Println(<- r.resp)
    }()

    go func() {
    r := NewRequest("127.0.0.1")
    requests <- r
    fmt.Println(<- r.resp)
    }()
    ```

    I don't even try to ask you about generic solution (without hardcoded strings and ints). I ask you to check if everything right with this code? Is it that simple?

    Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I don't want everybody to wait for slow clients. Yes? And what if I have too many slow clients? Maybe I have to handle this somehow.

    Is this part `requests <- r` that simple? What if my actor (server) is too busy to reply now? Maybe I need to handle timeouts here...

    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to hold requests until initialization is finished.

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate. 98% of time I don't want to see this `resp: make(chan int, ?)` and I really don't want to think what should I put instead of `?`.

    **99% of time I don't really care if response is delivered with a channel or a magical unicorn brought it on its horn.**

    ### And counting

    There are many other common concurrency situations. I think you've already got the idea.

    ## The Pain

    You can tell me, that described patterns are not common. But.. I have to implement almost all of them in all my projects. Every. Single. Time. Maybe I’m just out of luck and you projects are that simple as tutorial for beginners.

    I know that most of you will tell "world is too hard and programming is too painful". I hasten to upset you: there are at least few examples of languages that solved this problem at least partially. Or at least working on solving it. Haskell and Scala type systems give you ability to build strong [high-level abstractions][haskell-book] or even custom [control flows][oz-style] to [deal](https://github.com/scala/async) with concurrency. As an opposite Clojure is dynamically typed that encourage you to distil and share [high level][clojure-async] [abstraction][clojure-trans].

    Make it works -> Make it beautiful -> Make it reusable.

    First step is done. What's next? Don't get me wrong, go is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?


    ## P.S. Building Twitter Analyzer

    About real-world pipelining.

    Probably you've already seen [Twitter Analytics](https://analytics.twitter.com/) which is really great. Assume for the second that it's not introduced yet and we have to run our own analysis: for given username calculate how many unique users saw (at least theoretically) each of his own tweet. How we can do this? Not that hard: read user's timeline, filter away all retweets and replies, for all other tweets ask for all retweeters, for each retweeter ask for list of followers, merge all retweeters' followers together and add own user's followers. What I want to have as a result of these steps: `map[TweetId][]Username` (retweeters) and `map[Username][]Username`. It would be enough to build fancy table to show to requester.

    Few technical details that you should be aware of:

    - Twitter API requires OAuth for each call and set strong limitations (450 calls per 15 minutes per each user). To deal with such limitation we're going to use predefined list of OAuth tokens (i.e. 50) organized into pool of workers where each worker is able to suspend himself before facing problems with limits.

    - Most Twitter API calls use pagination for results with `since_id` or `max_id` continuations. So you can't rely on that fact that single call to worker will return you full result.

    [Example of rough implementation](https://gist.github.com/kachayev/50d89615101444cd62ad). Note, that there is no need for you to understand everything in this file. Just the opposite. If you can't understand it after quick screening then we're on the right way.

    So what do we have here?

    1. Few stages of computations: `TimelineReader` -> `RetweetersReader` -> `FollowersReader` -> `FinalReducer`.

    2. Self-stage messaging. All stages are recursive cause of pagination. It means that each stage emits messages both to next stage and to itself. It's much harder to deal with cancellation in this case. Or even find out when everything is done on single stage.

    3. Early propagation. There are at least 2 cases here: for the first in order to collect mapping from `TweetId` to `[]Username` we need to send collected info directly from `RetweetersReader` to `FinalReducer`; for the second we know from very beginning that we need to fetch followers for initial user, so his username should be emitted to `RetweetersReader` bypassing `TimelineReader` stage.

    4. Middleware reducers. `FollowersReader` is not only a pipe. It's a reducer for usernames that we've already seen (cause you don't want to duplicate you work).

    5. Long running workers. You can't just wait for workers shutdown in many cases, i.e. when you're implementing a server that should respond to many clients simultaneously.

    [scala-pmap]: http://docs.scala-lang.org/overviews/parallel-collections/overview.html

    [clojure-pmap]: http://clojuredocs.org/clojure_core/clojure.core/pmap

    [haskell-book]: http://www.amazon.com/Parallel-Concurrent-Programming-Haskell-Multithreaded/dp/1449335942

    [oz-style]: http://doc.akka.io/docs/akka/2.0.1/scala/dataflow.html

    [clojure-async]: https://github.com/clojure/core.async

    [go-meetup]: http://www.meetup.com/uagolang/events/188657172/

    [rob-pike]: http://talks.golang.org/2012/concurrency.slide#1

    [clojure-trans]: http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming
  5. @kachayev kachayev revised this gist Sep 14, 2014. No changes.
  6. @kachayev kachayev revised this gist Sep 14, 2014. 1 changed file with 2 additions and 447 deletions.
    449 changes: 2 additions & 447 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ Take a closer look to pipeline problem. Is it really a pipeline? No… "...for e

    ## So What About Patterns?

    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. They are only a transport layer, we need application level to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)), otherwise you will find yourself in constantly digging through low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce.
    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. They are only a transport layer. We need application level abstractions to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)), otherwise you will find yourself in constantly digging through low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce. Check [Erlang OTP](http://learnyousomeerlang.com/what-is-otp) that aims to solve the same problem: to protect you from low-level message passing code.

    What is the problem with low-level code? There is a great article ["Edward C++Hands"](http://bartoszmilewski.com/2013/09/19/edward-chands/):

    @@ -34,449 +34,4 @@ At [Kyiv Go Meetup][go-meetup] I experienced the same situation: 20 lines of cle

    Ok. Let’s try to collect such patterns. From work experience, from books, from other languages (yeah, guys, I know that it's hard to believe but there are several other languages also designed for concurrency).

    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about the network of channels. Not about your application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).

    ```go
    func merge(cs ...<-chan int) <-chan int {
    var wg sync.WaitGroup
    out := make(chan int)

    // Start an output goroutine for each input channel in cs. output
    // copies values from c to out until c is closed, then calls wg.Done.
    output := func(c <-chan int) {
    for n := range c {
    out <- n
    }
    wg.Done()
    }
    wg.Add(len(cs))
    for _, c := range cs {
    go output(c)
    }

    // Start a goroutine to close out once all the output goroutines are
    // done. This must start after the wg.Add call.
    go func() {
    wg.Wait()
    close(out)
    }()
    return out
    }
    ```

    Hm... `<-chan int`. Not that abstract to reuse in my own application (i.e. move to library)... And not that obvious to reimplement each time when I need it. How to make it reusable? `<-chan interface{}`? Welcome to the land of types casting and runtime panics. If you want to implement high level fan-in (merge) you’re losing type safety. The same (unfortunately) goes for all other patterns.

    What I really want here is:

    ```go
    func merge[T](cs ...<-chan T) <-chan T
    ```

    Yeah, I know that Go [doesn't have generics](http://golang.org/doc/faq#generics) because who ever need them?

    ## What is the Weather Now?

    Return to patterns. Let’s analyse hypothetical project that’s really close to practical experience in server-side development. We need a server that accepts request about weather for a given USA state and respond with info collected from [OpenWeatherMap](http://openweathermap.org/api). In such a way:

    ```shell
    $ http localhost:4912/weather?q=CA
    HTTP/1.1 200 OK
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Methods: GET, POST
    Access-Control-Allow-Origin: *
    Connection: keep-alive
    Content-Type: application/json; charset=utf-8
    ```

    ```json

    [{
    "clouds": {
    "all": 40
    },
    "id": 5391959,
    "main": {
    "temp": 288.89,
    "temp_max": 291.48,
    "temp_min": 286.15
    },
    "name": "San Francisco",
    "weather": [
    {
    "description": "mist",
    "icon": "50d",
    "id": 701,
    "main": "Mist"
    }
    ]
    }, {
    "clouds": {
    "all": 90
    },
    "id": 5368361,
    "main": {
    "temp": 292.83,
    "temp_max": 296.15,
    "temp_min": 289.15
    },
    "name": "Los Angeles",
    "weather": [
    {
    "description": "mist",
    "icon": "50d",
    "id": 701,
    "main": "Mist"
    }
    ]
    }]
    ```

    ### Pmap

    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We've talked about such pattern already. It's `pmap`. And I want my code to look like

    ```go
    chanCities := findCities(state)
    resolver := func(name City) Weather { return openWeatherMap.AskFor(name) }
    weather := chanCities.Par.Map(resolver)
    ```

    or in case of bounded parallelism

    ```go
    chanCities := findCities(state)
    pool := NewWorkers(20)
    resolver := func(w Worker, name City) Weather { return w.AskFor(name) }
    weather := chanCities.Par.BoundedMap(pool, resolver)
    ```

    That's it. I want all this `<-done` synchronizations and `select` sacramentals to be entire hidden.

    ### Futures & Promises

    It can take a long time to get current weather, i.e. when you have long list of cities for concrete state. Off course you don't want to duplicate API calls so you should manage simultaneous requests somehow:

    ```go
    func collect(state string) Weather {
    calc, ok := calculations.get(state) // check if it's in progress
    if !ok {
    calc.calculations.run(state) // run otherwise
    }
    return calc.Wait() // wait until done
    }
    ```

    This is so called [future/promise](http://en.wikipedia.org/wiki/Futures_and_promises). From Wiki:

    > They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
    I heard few times from different people that go `future` is a simple:

    ```go
    f := make(chan int, 1)
    ```

    Which is wrong cause all waiters should get result. And this version is also wrong:

    ```go
    f := make(chan int, 1)
    v <- f
    f <- v
    // use v here
    ```

    Because it's impossible to manage resources this way. And I wish you good luck to find the bug if somebody missed `f <- v` part in his code.

    It's not that hard though to implement `promise` directly storing all waiters (I'm not sure that this code is really bugs free):

    ```go
    type PromiseDelivery chan interface{}
    type Promise struct {
    sync.RWMutex
    value interface{}
    waiters []PromiseDelivery
    }

    func (p *Promise) Deliver(value interface{}) {
    p.Lock()
    defer p.Unlock()
    p.value = value
    for _, w := range p.waiters {
    locW := w
    go func(){
    locW <- value
    }()
    }
    }

    func (p *Promise) Value() interface{} {
    if p.value != nil {
    return p.value
    }

    delivery := make(PromiseDelivery)
    p.waiters = append(p.waiters, delivery)
    return <-delivery
    }

    func NewPromise() *Promise {
    return &Promise{
    value: nil,
    waiters: []PromiseDelivery{},
    }
    }
    ```

    How to use it?

    ```go
    p := NewPromise()
    go func(){
    p.Deliver(42)
    }()
    p.Value().(int) // blocks and returns interface{} when ready
    ```

    But `interface{}` and type casting are already here. What do I really want here?

    ```go
    // .. somewhere in well-tested library or even in stdlib
    type PromiseDelivery[T] chan T
    type Promise[T] struct {
    sync.RWMutex
    value T
    waiters []PromiseDelivery[T]
    }
    func (p *Promise[T]) Deliver(value T)
    func (p *Promise[T]) Value() T
    func NewPromise[T]() *Promise[T]

    // in my code:
    v := NewPromise[int]()
    go func(){
    v.Deliver("woooow!") // compilation error
    v.Deliver(42)
    }()
    v.Value() // blocks and returns 42, not interface{}
    ```

    No, sure, nobody needs generics. What the hell I'm talking about?

    You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` operations in single goroutine. You can also introduce special `.ValueWithTimeout` method which will be really helpful for end users. And there're lots of other "you can...". Despite the fact that we're talking about 20 lines of code (that probably will grow each time you discovered more details of futures/promises interactions). Do I really need to know (or even think) about channels that delivered me the value? No.

    ### Pub/sub

    Assume that we want to build real-time service. So now our client can open websocket connection with `q=CA` request and gets instant updates about weather changes in California. Usually it will look like:

    ```go
    // deliverer
    calculation.WhenDone(func(state string, w Weather) {
    broker.Publish("CA", w)
    })

    // client
    ch := broker.Subscribe("CA")
    for update := range ch {
    w.Write(update.Serialize())
    }
    ```

    It's a typical pub/sub. You can learn about it from [Advanced Go Patterns](http://blog.golang.org/advanced-go-concurrency-patterns) talk and even find ready-to-use [implementations](https://github.com/tuxychandru/pubsub). The problems is that [they](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L34) [are](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L48) [all](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L54) [about](https://github.com/tuxychandru/pubsub/blob/master/pubsub.go#L58) interfaces.

    Is it possible to implement:

    ```go
    broker := NewBroker[String, Weather]()
    // so that
    broker.Subs(42) // compilation failure
    // and
    broker.Subs("CA") // returns (chan Weather) not (chan interface{})
    ```

    Sure! If you're brave enough to copy-paste code from project to project with small fixes here and there.

    ### Map/filter

    Assume that we want to give our users more flexibility and we're introducing new query params: `show` which can be equal to `all|temp|wind|icon`.

    Probably you'll start from simples:

    ```go
    ch := broker.Subscribe("CA")
    for update := range ch {
    temps := []Temp
    for _, t := update.Temp {
    temps = append(temps, t)
    }

    w.Write(temps)
    }
    ```

    But after 10 such methods you'll realize that it's not composable and even boring. Maybe you need

    ```go
    ch := broker.Subscribe("CA").Map(func(w Weather) Temp { return w.Temp })
    for update := range ch {
    w.Write(update)
    }
    ```

    Wait, did I just say that channel is a [functor](http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)? As well as Future/Promise.

    ```go
    p := NewPromise().Map(func(w Weather) Temp { return w.Temp })
    go func(){
    p.Deliver(Weather{Temp{42}})
    }()
    p.Value().(Temp) // Temp, not Weather
    ```

    Which means that I can reuse the same code for channels and futures. You may also end up with something like [transducers](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming). I frequently use in ClojureScript code tricks like

    ```clojure
    (->> (send url) ;; returns chan, put single value to it {:status 200 :result 42} when ready
    (async/filter< #(= 200 (:status %))) ;; check that :status is 200
    (async/map< :result)) ;; expose only 42 to end user
    ;; note, that it will close all channels (including implicit intermediate one) properly
    ```

    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably, not. In this case why I'm allowed to do `make(chan int)` and not allowed to do `make(Future int)`?

    ### Request/Reply

    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.

    So for the first we need goroutine that will be responsible for collecting number of requests.

    ```go
    req := make(chan string)
    go func() { // wow, look here - it's an actor!
    m := map[string]int{}
    for r := range req {
    if v, ok := m[r]; !ok {
    m[r] = 1
    } else {
    m[r] = v + 1
    }
    }
    }()

    go func() {
    req <- "127.0.0.2"
    }()

    go func() {
    req <- "127.0.0.1"
    }()
    ```

    It's easy. Now can calculate number of requests for each IP. Not that much... We also have to be able to ask permissions to execute request.

    ```go
    type Req struct {
    ip string
    resp chan int
    }

    func NewRequest(ip string) *Req {
    return &Req{ip, make(chan int)}
    }

    requests := make(chan *Req)

    go func() {
    m := map[string]int{}
    for r := range requests {
    if v, ok := m[r.ip]; !ok {
    m[r.ip] = 1
    } else {
    m[r.ip] = v + 1
    }
    r.resp <- m[r.ip]
    }
    }()

    go func() {
    r := NewRequest("127.0.0.2")
    requests <- r
    fmt.Println(<- r.resp)
    }()

    go func() {
    r := NewRequest("127.0.0.1")
    requests <- r
    fmt.Println(<- r.resp)
    }()
    ```

    I don't even try to ask you about generic solution (without hardcoded strings and ints). I ask you to check if everything right with this code? Is it that simple?

    Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I don't want everybody to wait for slow clients. Yes? And what if I have too many slow clients? Maybe I have to handle this somehow.

    Is this part `requests <- r` that simple? What if my actor (server) is too busy to reply now? Maybe I need to handle timeouts here...

    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to hold requests until initialization is finished.

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate. 98% of time I don't want to see this `resp: make(chan int, ?)` and I really don't want to think what should I put instead of `?`.

    **99% of time I don't really care if response is delivered with a channel or a magical unicorn brought it on its horn.**

    ### And counting

    There are many other common concurrency situations. I think you've already got the idea.

    ## The Pain

    You can tell me, that described patterns are not common. But.. I have to implement almost all of them in all my projects. Every. Single. Time. Maybe I’m just out of luck and you projects are that simple as tutorial for beginners.

    I know that most of you will tell "world is too hard and programming is too painful". I hasten to upset you: there are at least few examples of languages that solved this problem at least partially. Or at least working on solving it. Haskell and Scala type systems give you ability to build strong [high-level abstractions][haskell-book] or even custom [control flows][oz-style] to [deal](https://github.com/scala/async) with concurrency. As an opposite Clojure is dynamically typed that encourage you to distil and share [high level][clojure-async] [abstraction][clojure-trans].

    Make it works -> Make it beautiful -> Make it reusable.

    First step is done. What's next? Don't get me wrong, go is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?


    ## P.S. Building Twitter Analyzer

    About real-world pipelining.

    Probably you've already seen [Twitter Analytics](https://analytics.twitter.com/) which is really great. Assume for the second that it's not introduced yet and we have to run our own analysis: for given username calculate how many unique users saw (at least theoretically) each of his own tweet. How we can do this? Not that hard: read user's timeline, filter away all retweets and replies, for all other tweets ask for all retweeters, for each retweeter ask for list of followers, merge all retweeters' followers together and add own user's followers. What I want to have as a result of these steps: `map[TweetId][]Username` (retweeters) and `map[Username][]Username`. It would be enough to build fancy table to show to requester.

    Few technical details that you should be aware of:

    - Twitter API requires OAuth for each call and set strong limitations (450 calls per 15 minutes per each user). To deal with such limitation we're going to use predefined list of OAuth tokens (i.e. 50) organized into pool of workers where each worker is able to suspend himself before facing problems with limits.

    - Most Twitter API calls use pagination for results with `since_id` or `max_id` continuations. So you can't rely on that fact that single call to worker will return you full result.

    [Example of rough implementation](https://gist.github.com/kachayev/50d89615101444cd62ad). Note, that there is no need for you to understand everything in this file. Just the opposite. If you can't understand it after quick screening then we're on the right way.

    So what do we have here?

    1. Few stages of computations: `TimelineReader` -> `RetweetersReader` -> `FollowersReader` -> `FinalReducer`.

    2. Self-stage messaging. All stages are recursive cause of pagination. It means that each stage emits messages both to next stage and to itself. It's much harder to deal with cancellation in this case. Or even find out when everything is done on single stage.

    3. Early propagation. There are at least 2 cases here: for the first in order to collect mapping from `TweetId` to `[]Username` we need to send collected info directly from `RetweetersReader` to `FinalReducer`; for the second we know from very beginning that we need to fetch followers for initial user, so his username should be emitted to `RetweetersReader` bypassing `TimelineReader` stage.

    4. Middleware reducers. `FollowersReader` is not only a pipe. It's a reducer for usernames that we've already seen (cause you don't want to duplicate you work).

    5. Long running workers. You can't just wait for workers shutdown in many cases, i.e. when you're implementing a server that should respond to many clients simultaneously.

    [scala-pmap]: http://docs.scala-lang.org/overviews/parallel-collections/overview.html

    [clojure-pmap]: http://clojuredocs.org/clojure_core/clojure.core/pmap

    [haskell-book]: http://www.amazon.com/Parallel-Concurrent-Programming-Haskell-Multithreaded/dp/1449335942

    [oz-style]: http://doc.akka.io/docs/akka/2.0.1/scala/dataflow.html

    [clojure-async]: https://github.com/clojure/core.async

    [go-meetup]: http://www.meetup.com/uagolang/events/188657172/

    [rob-pike]: http://talks.golang.org/2012/concurrency.slide#1

    [clojure-trans]: http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming
    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about the network of channels
  7. @kachayev kachayev revised this gist Sep 14, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ By [@kachayev](https://twitter.com/kachayev)

    ## Intro

    Go was designed for building concurrency application easily so it has goroutines for running independent computations and channels to communicate with each other. We've all heard this story before. All examples and tutorials look just fine: we can create a new channel, we can send to a channel, we can read from a channel, we even have the nifty, elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…
    Go was designed for building concurrency applications easily so it has goroutines for running independent computations and channels to communicate with each other. We've all heard this story before. All examples and tutorials look just fine: we can create a new channel, we can send to a channel, we can read from a channel, we even have the nifty, elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…

    ![channels](https://pbs.twimg.com/media/BvBSJJQCAAAWH8e.jpg)

  8. @kachayev kachayev revised this gist Sep 12, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -74,9 +74,9 @@ func merge[T](cs ...<-chan T) <-chan T

    Yeah, I know that Go [doesn't have generics](http://golang.org/doc/faq#generics) because who ever need them?

    ## What The Weather is Now?
    ## What is the Weather Now?

    Return to patterns. Let’s analyse hypothetical project that’s really close to practical experience in server-side development. We need server that accepts request about weather for given USA state and respond with info collected from [OpenWeatherMap](http://openweathermap.org/api). In such way:
    Return to patterns. Let’s analyse hypothetical project that’s really close to practical experience in server-side development. We need a server that accepts request about weather for a given USA state and respond with info collected from [OpenWeatherMap](http://openweathermap.org/api). In such a way:

    ```shell
    $ http localhost:4912/weather?q=CA
  9. @kachayev kachayev revised this gist Sep 12, 2014. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -22,19 +22,19 @@ Take a closer look to pipeline problem. Is it really a pipeline? No… "...for e

    ## So What About Patterns?

    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. They are only a transport layer, we need application level to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)). Otherwise you will find yourself in process of constant digging in low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce.
    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. They are only a transport layer, we need application level to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)), otherwise you will find yourself in constantly digging through low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce.

    What the problem with low-level code? There is a great article ["Edward C++Hands"](http://bartoszmilewski.com/2013/09/19/edward-chands/):
    What is the problem with low-level code? There is a great article ["Edward C++Hands"](http://bartoszmilewski.com/2013/09/19/edward-chands/):

    > Having scissors for hands in not all that bad. Edward has many talents: he can, for instance, create stunning dog hairdos. Don’t get me wrong — there were many stunning dog hairdos on display (I mean C++ code that was elegant and simple) but the bulk of the conference was about how to avoid mutilation and how to deliver first aid in case of accidental amputation.
    At [Kyiv Go Meetup][go-meetup] I experienced the same situation: 20 lines of clean and readable code on a single slide. One non-trivial race condition and one possible runtime panic. Was it obvious for all listeners? No. Not even for half of them.

    ## Any Reason for Panic?

    Ok. Let’s try to collect such patterns. From work experience, from books, from other languages (yeah, guys, I know that it's hard to believe but there are few other languages also designed for concurrency).
    Ok. Let’s try to collect such patterns. From work experience, from books, from other languages (yeah, guys, I know that it's hard to believe but there are several other languages also designed for concurrency).

    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about network of channels. Not about you application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).
    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about the network of channels. Not about your application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).

    ```go
    func merge(cs ...<-chan int) <-chan int {
    @@ -64,15 +64,15 @@ func merge(cs ...<-chan int) <-chan int {
    }
    ```

    Hm... `<-chan int`. Not that abstract to reuse in my own application (i.e. move to library)... And not that obvious to reimplement each time when I need it. How to do it reusable? `<-chan interface{}`? Welcome to the land of types casting and runtime panics. If you want to implement high level fan-in (merge) you’re losing type safety. The same (unfortunately) goes for all other patterns.
    Hm... `<-chan int`. Not that abstract to reuse in my own application (i.e. move to library)... And not that obvious to reimplement each time when I need it. How to make it reusable? `<-chan interface{}`? Welcome to the land of types casting and runtime panics. If you want to implement high level fan-in (merge) you’re losing type safety. The same (unfortunately) goes for all other patterns.

    What I really want here is:

    ```go
    func merge[T](cs ...<-chan T) <-chan T
    ```

    Yeah, I know that Go [doesn't have generics](http://golang.org/doc/faq#generics) cause who ever need them?
    Yeah, I know that Go [doesn't have generics](http://golang.org/doc/faq#generics) because who ever need them?

    ## What The Weather is Now?

  10. @kachayev kachayev revised this gist Sep 12, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -8,17 +8,17 @@ By [@kachayev](https://twitter.com/kachayev)

    ## Intro

    Go was designed for building concurrency application easily so it has goroutines for running independent computations and channels to communicate with each other. We've all heard this story before. All examples and tutorials look just great: we can create new channel, we can send to channel, we can read from channel, we even have such nifty and elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…
    Go was designed for building concurrency application easily so it has goroutines for running independent computations and channels to communicate with each other. We've all heard this story before. All examples and tutorials look just fine: we can create a new channel, we can send to a channel, we can read from a channel, we even have the nifty, elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…

    ![channels](https://pbs.twimg.com/media/BvBSJJQCAAAWH8e.jpg)

    It’s so cool when you find yourself writing tutorial for beginners! And it's a bit painful when you are trying to implement big and sophisticated system(s). Channels are [primitives](https://golang.org/doc/). They are low-level building blocks and I doubt if you want to work with them on daily basis.
    It’s so cool to find yourself writing tutorial for beginners! And it's a bit painful when you are trying to implement big and sophisticated system(s). Channels are [primitives](https://golang.org/doc/). They are low-level building blocks and I highly doubt you want to work with them on daily basis.

    Look at ["advanced patterns"](http://blog.golang.org/advanced-go-concurrency-patterns) and ["pipeline"](http://blog.golang.org/pipelines). Not that simple right? Too many things that I should be aware of and constantly keep in my memory: when and how to close channels, how to propagate errors, how to free resources. I'm complaining about this not cause I tried to implement something and failed. But cause I work with such stuff every single day.
    Look at ["advanced patterns"](http://blog.golang.org/advanced-go-concurrency-patterns) and ["pipeline"](http://blog.golang.org/pipelines). Not that simple right? Too many things to keep in mind and constantly memorize: when and how to close channels, how to propagate errors, how to free resources. I'm complaining about this not because I've tried implementing something and failed. But because I work with stuff like this every single day.

    You can say that it's not necessary for beginner to understand all details on the picture. But... Are described patterns really "advanced"? Unfortunately, the answer is *NO*. They're basic and common.
    You can say that it's not necessary for beginner to understand all of the details of the whole picture. But... are described patterns really "advanced"? Unfortunately, the answer is *NO*. They're basic and common.

    Take a closer look to pipeline problem. Is it really pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to single `map[string]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require from me so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at the real pipelining problem - I will describe one at the end of the article (see "Building Twitter Analyzer" paragraph).
    Take a closer look to pipeline problem. Is it really a pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to a single `map[string]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require that I enter so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at the real pipelining problem - I will describe one at the end of the article (see "Building Twitter Analyzer" paragraph).

    ## So What About Patterns?

  11. @kachayev kachayev revised this gist Sep 12, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -8,21 +8,21 @@ By [@kachayev](https://twitter.com/kachayev)

    ## Intro

    Go was designed for building concurrency application easily so it has goroutines for running independent computations and channels to communicate with each other. We heard this story for many times. All examples and tutorials look just great: we can create new channel, we can send to channel, we can read from channel, we even have such nifty and elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…
    Go was designed for building concurrency application easily so it has goroutines for running independent computations and channels to communicate with each other. We've all heard this story before. All examples and tutorials look just great: we can create new channel, we can send to channel, we can read from channel, we even have such nifty and elegant select statement (__btw, why do we still have statements in 21th century?__), blocking reads and buffers…

    ![channels](https://pbs.twimg.com/media/BvBSJJQCAAAWH8e.jpg)

    It’s so cool when you find yourself writing tutorial for beginners! And it's painful a bit when you are trying to implement big and sophisticated system(s). Channels are [primitives](https://golang.org/doc/). They are low-level building blocks and I doubt if you want to work with them on daily basis.
    It’s so cool when you find yourself writing tutorial for beginners! And it's a bit painful when you are trying to implement big and sophisticated system(s). Channels are [primitives](https://golang.org/doc/). They are low-level building blocks and I doubt if you want to work with them on daily basis.

    Look at ["advanced patterns"](http://blog.golang.org/advanced-go-concurrency-patterns) and ["pipeline"](http://blog.golang.org/pipelines). Not that simple right? Too many things that I should be aware of and constantly keep in my memory: when and how to close channels, how to propagate errors, how to free resources. I'm complaining about this not cause I tried to implement something and failed. But cause I work with such stuff every single day.

    You can say that it's not necessary for beginner to understand all details on the picture. But... Are described patterns really "advanced"? Unfortunately, the answer is *NO*. They're basic and common.

    Take a closer look to pipeline problem. Is it really pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to single `map[stirng]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require from me so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at real pipelining problem - I will describe one at the end of the article (see "Building Twitter Analyzer" paragraph).
    Take a closer look to pipeline problem. Is it really pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to single `map[string]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require from me so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at the real pipelining problem - I will describe one at the end of the article (see "Building Twitter Analyzer" paragraph).

    ## So What About Patterns?

    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. It’s only transport layer, we need application level to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)). Otherwise you will find yourself in process of constant digging in low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce.
    To develop real-world applications fast enough we should be able to distil higher level abstractions than primitive channels. They are only a transport layer, we need application level to write programs (compare to [OSI](http://en.wikipedia.org/wiki/OSI_model)). Otherwise you will find yourself in process of constant digging in low-level details of your channels network trying to find why it doesn’t work. Only on production machine. From time to time. Without any reasonable steps to reproduce.

    What the problem with low-level code? There is a great article ["Edward C++Hands"](http://bartoszmilewski.com/2013/09/19/edward-chands/):

    @@ -332,7 +332,7 @@ go func(){
    p.Value().(Temp) // Temp, not Weather
    ```

    Which means that I can reuse the same code for channels and futures simply declaring operation on that values that I don't have just now. You may also end up with something like [transducers](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming). I frequently use in ClojureScript code tricks like
    Which means that I can reuse the same code for channels and futures. You may also end up with something like [transducers](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming). I frequently use in ClojureScript code tricks like

    ```clojure
    (->> (send url) ;; returns chan, put single value to it {:status 200 :result 42} when ready
  12. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@ Look at ["advanced patterns"](http://blog.golang.org/advanced-go-concurrency-pat

    You can say that it's not necessary for beginner to understand all details on the picture. But... Are described patterns really "advanced"? Unfortunately, the answer is *NO*. They're basic and common.

    Take a closer look to pipeline problem. Is it really pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to single `map[stirng]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require from me so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at real pipelining problem - I described one at the end of the article.
    Take a closer look to pipeline problem. Is it really pipeline? No… "...for each path from directory calculate `MD5` checksum and collect result to single `map[stirng]string`...". It’s just a `pmap` (parallel map). Or `pmap` with `pool of executors` in case of bounded parallelism. And `pmap` should not require from me so [many][scala-pmap] [lines][clojure-pmap] of code. Wanna look at real pipelining problem - I will describe one at the end of the article (see "Building Twitter Analyzer" paragraph).

    ## So What About Patterns?

    @@ -439,7 +439,7 @@ Make it works -> Make it beautiful -> Make it reusable.
    First step is done. What's next? Don't get me wrong, go is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?


    ## P.S.1. Building Twitter Analyzer
    ## P.S. Building Twitter Analyzer

    About real-world pipelining.

  13. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # Channels Are Not Enough

    ## ... or Why Pipelining Is Not That Easy
    **... or Why Pipelining Is Not That Easy**

    [Golang](https://talks.golang.org/2012/concurrency.slide#1) [Concurrency](http://blog.golang.org/advanced-go-concurrency-patterns) [Patterns](http://blog.golang.org/pipelines) for brave and smart.

  14. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,6 @@
    # Channels Are Not Enough or Why Pipelining Is Not That Easy
    # Channels Are Not Enough

    ## ... or Why Pipelining Is Not That Easy

    [Golang](https://talks.golang.org/2012/concurrency.slide#1) [Concurrency](http://blog.golang.org/advanced-go-concurrency-patterns) [Patterns](http://blog.golang.org/pipelines) for brave and smart.

  15. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -131,7 +131,7 @@ Content-Type: application/json; charset=utf-8

    ### Pmap

    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We talked about such patter already. It's `pmap`. And I want my code to look like
    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We've talked about such pattern already. It's `pmap`. And I want my code to look like

    ```go
    chanCities := findCities(state)
  16. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -336,7 +336,7 @@ Which means that I can reuse the same code for channels and futures simply decla
    (->> (send url) ;; returns chan, put single value to it {:status 200 :result 42} when ready
    (async/filter< #(= 200 (:status %))) ;; check that :status is 200
    (async/map< :result)) ;; expose only 42 to end user
    ;; note, that it will close all channels properly
    ;; note, that it will close all channels (including implicit intermediate one) properly
    ```

    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably, not. In this case why I'm allowed to do `make(chan int)` and not allowed to do `make(Future int)`?
  17. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 1 addition and 5 deletions.
    6 changes: 1 addition & 5 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -129,13 +129,9 @@ Content-Type: application/json; charset=utf-8
    }]
    ```

    ### Pipeline

    Let's start from something that we already know. Assume that we store information about states and cities in file system, where each state is represented by a single file and any line in this file is either a name of a city or a name of cities group (that should be found in another file). You have to collect all cities recursively. With context handing, error propagation and asynchronously emitting city names to the next stage - API calls to OpenWeatherMap.

    ### Pmap

    For each city call OpenWeatherMap API and collect results to single `map[City]Weather`. We talked about such patter already. It's `pmap`. And I want my code to look like
    Let's start from something that we already know. So, we've got request `?q=CA`. I don't want to specify where we're going to find list of relative cities. We can use for this database, in-memory cache or whatever reasonable. Assume that we have magical `findCities(state)` function that returns `chan City` (as most universal go representation for LazySeq). Next? For each city we have to call OpenWeatherMap API and collect results to single `map[City]Weather`. We talked about such patter already. It's `pmap`. And I want my code to look like

    ```go
    chanCities := findCities(state)
  18. @kachayev kachayev revised this gist Sep 3, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -264,7 +264,7 @@ v.Value() // blocks and returns 42, not interface{}

    No, sure, nobody needs generics. What the hell I'm talking about?

    Do I really need here to know (or even think) about channels that delivered me the value? No.
    You can also avoid `p.Lock()` using `select` to listen to `deliver` and `wait` operations in single goroutine. You can also introduce special `.ValueWithTimeout` method which will be really helpful for end users. And there're lots of other "you can...". Despite the fact that we're talking about 20 lines of code (that probably will grow each time you discovered more details of futures/promises interactions). Do I really need to know (or even think) about channels that delivered me the value? No.

    ### Pub/sub

    @@ -331,7 +331,7 @@ p := NewPromise().Map(func(w Weather) Temp { return w.Temp })
    go func(){
    p.Deliver(Weather{Temp{42}})
    }()
    p.Value().(Temp) // Temp not a Weather
    p.Value().(Temp) // Temp, not Weather
    ```

    Which means that I can reuse the same code for channels and futures simply declaring operation on that values that I don't have just now. You may also end up with something like [transducers](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming). I frequently use in ClojureScript code tricks like
  19. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -343,6 +343,8 @@ Which means that I can reuse the same code for channels and futures simply decla
    ;; note, that it will close all channels properly
    ```

    Do I really have to worry if `x` is a channel or a future if I can simply do `x.Map(transformation)` and get back value of the same type? Probably, not. In this case why I'm allowed to do `make(chan int)` and not allowed to do `make(Future int)`?

    ### Request/Reply

    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.
  20. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -264,6 +264,8 @@ v.Value() // blocks and returns 42, not interface{}

    No, sure, nobody needs generics. What the hell I'm talking about?

    Do I really need here to know (or even think) about channels that delivered me the value? No.

    ### Pub/sub

    Assume that we want to build real-time service. So now our client can open websocket connection with `q=CA` request and gets instant updates about weather changes in California. Usually it will look like:
  21. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -242,6 +242,7 @@ p.Value().(int) // blocks and returns interface{} when ready
    But `interface{}` and type casting are already here. What do I really want here?

    ```go
    // .. somewhere in well-tested library or even in stdlib
    type PromiseDelivery[T] chan T
    type Promise[T] struct {
    sync.RWMutex
    @@ -251,6 +252,14 @@ type Promise[T] struct {
    func (p *Promise[T]) Deliver(value T)
    func (p *Promise[T]) Value() T
    func NewPromise[T]() *Promise[T]

    // in my code:
    v := NewPromise[int]()
    go func(){
    v.Deliver("woooow!") // compilation error
    v.Deliver(42)
    }()
    v.Value() // blocks and returns 42, not interface{}
    ```

    No, sure, nobody needs generics. What the hell I'm talking about?
  22. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -172,7 +172,7 @@ This is so called [future/promise](http://en.wikipedia.org/wiki/Futures_and_prom

    > They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
    I heard few time from different people that go `future` is:
    I heard few times from different people that go `future` is a simple:

    ```go
    f := make(chan int, 1)
    @@ -187,7 +187,7 @@ f <- v
    // use v here
    ```

    Because it's impossible to manage resources this way. And I wish you luck to find the bug if somebody missed `f <- v` part in his code.
    Because it's impossible to manage resources this way. And I wish you good luck to find the bug if somebody missed `f <- v` part in his code.

    It's not that hard though to implement `promise` directly storing all waiters (I'm not sure that this code is really bugs free):

  23. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -32,7 +32,7 @@ At [Kyiv Go Meetup][go-meetup] I experienced the same situation: 20 lines of cle

    Ok. Let’s try to collect such patterns. From work experience, from books, from other languages (yeah, guys, I know that it's hard to believe but there are few other languages also designed for concurrency).

    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many way, but still about network of channels. Not about you application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).
    Rob Pike [talks][rob-pike] about Fan-in, Fan-out. It’s useful in many ways, but still about network of channels. Not about you application. In any case, let's check (shamelessly stolen from [here](http://blog.golang.org/pipelines)).

    ```go
    func merge(cs ...<-chan int) <-chan int {
  24. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -405,7 +405,7 @@ Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I

    Is this part `requests <- r` that simple? What if my actor (server) is too busy to reply now? Maybe I need to handle timeouts here...

    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to handle calls until initialization is finished.
    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to hold requests until initialization is finished.

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

  25. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -425,7 +425,7 @@ I know that most of you will tell "world is too hard and programming is too pain

    Make it works -> Make it beautiful -> Make it reusable.

    First step is done. What's next? Of course channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?
    First step is done. What's next? Don't get me wrong, go is a perspective language: channels and goroutines are way much better than i.e. `pthread`, but should we really stop here?


    ## P.S.1. Building Twitter Analyzer
  26. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -411,7 +411,7 @@ What about priority of calls? I.e. when I need to implement `Dump` procedure for

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate. 98% of time I don't want to see this `resp: make(chan int, ?)` and I really don't want to think what should I put instead of `?`.

    **99% of time I don't really care if response is delivered with channel or magical unicorn brought it on its horn.**
    **99% of time I don't really care if response is delivered with a channel or a magical unicorn brought it on its horn.**

    ### And counting

  27. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -279,9 +279,9 @@ Is it possible to implement:
    ```go
    broker := NewBroker[String, Weather]()
    // so that
    broker.Subs(42) // failes
    broker.Subs(42) // compilation failure
    // and
    broker.Subs("CA") // returns (chan Weather)
    broker.Subs("CA") // returns (chan Weather) not (chan interface{})
    ```

    Sure! If you're brave enough to copy-paste code from project to project with small fixes here and there.
    @@ -409,7 +409,9 @@ And from time to time I need to specify initialization process.. And cleanup...

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate.
    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate. 98% of time I don't want to see this `resp: make(chan int, ?)` and I really don't want to think what should I put instead of `?`.

    **99% of time I don't really care if response is delivered with channel or magical unicorn brought it on its horn.**

    ### And counting

  28. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 21 additions and 7 deletions.
    28 changes: 21 additions & 7 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -336,11 +336,11 @@ Which means that I can reuse the same code for channels and futures simply decla

    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.

    So for the first we need goroutine that will be responsible for requests calculation.
    So for the first we need goroutine that will be responsible for collecting number of requests.

    ```go
    req := make(chan string)
    go func() {
    go func() { // wow, look here - it's an actor!
    m := map[string]int{}
    for r := range req {
    if v, ok := m[r]; !ok {
    @@ -372,11 +372,11 @@ func NewRequest(ip string) *Req {
    return &Req{ip, make(chan int)}
    }

    req := make(chan *Req)
    requests := make(chan *Req)

    go func() {
    m := map[string]int{}
    for r := range req {
    for r := range requests {
    if v, ok := m[r.ip]; !ok {
    m[r.ip] = 1
    } else {
    @@ -388,18 +388,32 @@ go func() {

    go func() {
    r := NewRequest("127.0.0.2")
    req <- r
    requests <- r
    fmt.Println(<- r.resp)
    }()

    go func() {
    r := NewRequest("127.0.0.1")
    req <- r
    requests <- r
    fmt.Println(<- r.resp)
    }()
    ```

    ... And counting
    I don't even try to ask you about generic solution (without hardcoded strings and ints). I ask you to check if everything right with this code? Is it that simple?

    Are you sure, that `r.resp <- m[r.ip]` is a good solution? No. Definitely not. I don't want everybody to wait for slow clients. Yes? And what if I have too many slow clients? Maybe I have to handle this somehow.

    Is this part `requests <- r` that simple? What if my actor (server) is too busy to reply now? Maybe I need to handle timeouts here...

    And from time to time I need to specify initialization process.. And cleanup... Both with timeouts. And ability to handle calls until initialization is finished.

    What about priority of calls? I.e. when I need to implement `Dump` procedure for my analytic system but I don't want to pause all users until analytics data is collected.

    And... Looks like `gen_server` in [Erlang](http://www.erlang.org/doc/man/gen_server.html). For sure I want it to be implemented once and shipped with well-documented library with high test coverage rate.

    ### And counting

    There are many other common concurrency situations. I think you've already got the idea.

    ## The Pain

  29. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 65 additions and 1 deletion.
    66 changes: 65 additions & 1 deletion concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -329,11 +329,75 @@ Which means that I can reuse the same code for channels and futures simply decla
    (->> (send url) ;; returns chan, put single value to it {:status 200 :result 42} when ready
    (async/filter< #(= 200 (:status %))) ;; check that :status is 200
    (async/map< :result)) ;; expose only 42 to end user
    ;; note, that it will close all channels properly
    ```

    ### Request/Reply

    Number of requests per each IP. not share memory, use communication. ok, we have actor with map state string/int. request with IP, respond with current limit.
    Assume that our users like our service and use it actively. So we decided to introduce simple API limitation: number of requests per each IP per day. It's simply to collect number of calls to single `map[string]int`. Go docs [says](http://blog.golang.org/share-memory-by-communicating) "Do not communicate by sharing memory; instead, share memory by communicating". Ok, looks like nice idea.

    So for the first we need goroutine that will be responsible for requests calculation.

    ```go
    req := make(chan string)
    go func() {
    m := map[string]int{}
    for r := range req {
    if v, ok := m[r]; !ok {
    m[r] = 1
    } else {
    m[r] = v + 1
    }
    }
    }()

    go func() {
    req <- "127.0.0.2"
    }()

    go func() {
    req <- "127.0.0.1"
    }()
    ```

    It's easy. Now can calculate number of requests for each IP. Not that much... We also have to be able to ask permissions to execute request.

    ```go
    type Req struct {
    ip string
    resp chan int
    }

    func NewRequest(ip string) *Req {
    return &Req{ip, make(chan int)}
    }

    req := make(chan *Req)

    go func() {
    m := map[string]int{}
    for r := range req {
    if v, ok := m[r.ip]; !ok {
    m[r.ip] = 1
    } else {
    m[r.ip] = v + 1
    }
    r.resp <- m[r.ip]
    }
    }()

    go func() {
    r := NewRequest("127.0.0.2")
    req <- r
    fmt.Println(<- r.resp)
    }()

    go func() {
    r := NewRequest("127.0.0.1")
    req <- r
    fmt.Println(<- r.resp)
    }()
    ```

    ... And counting

  30. @kachayev kachayev revised this gist Sep 2, 2014. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions concurrency-in-go.md
    Original file line number Diff line number Diff line change
    @@ -139,15 +139,16 @@ For each city call OpenWeatherMap API and collect results to single `map[City]We

    ```go
    chanCities := findCities(state)
    weather := chanCities.Par.Map(func(name City){ return openWeatherMap.AskFor(name) })
    resolver := func(name City) Weather { return openWeatherMap.AskFor(name) }
    weather := chanCities.Par.Map(resolver)
    ```

    or in case of bounded parallelism

    ```go
    chanCities := findCities(state)
    pool := NewWorkers(20)
    resolver := func(w Worker, name City){ return worker.AskFor(name) }
    resolver := func(w Worker, name City) Weather { return w.AskFor(name) }
    weather := chanCities.Par.BoundedMap(pool, resolver)
    ```