Channels Are Not Enough
gist.github.com
Channels Are Not Enough
1–10 of 224 posts
Re: Channels Are Not Enough
#2Just like Erlang has explicit processes and message sending primitives So it is pretty simple and concise at that level. In order to build large systems there is OTP (or e2) that embodies and abstracts away some common patterns/behaviours: gen_event, gen_server, gen_fsm, supervisors, logging, distribution between nodes etc.
I imagine over time go will acquire those kind of libraries (maybe it already has them?).
There is also an interesting duality between Erlang and Go. In one case there are explicit processes (identified by PIDs) + an anonymous (implicit) mailbox. Where go has anonymous goroutines but explicitly identifiably channels. It seems they are duals. You can simulate one with another. And you can build concurrency patterns on top of them.
I personally prefer Erlang's model to think about concurrency. There is an active entity -- a client request, a server, a socket handler, it has a an id/name, it can be monitored for liveliness, it can be halted, upgraded, killed, can send messages to it. Somehow to me that makes it easier to map to concurrent problem domains. Channels can ultimately do the same things but it is harder for me to design using goroutines.
Re: Channels Are Not Enough
#3Yeah it seem channels are basic primitives. Kind of a like a class in OO programming. Just like Erlang has explicit processes and message sending primitives So it is pretty simple and concise at that level. In order to build large systems there is OTP (or e2) that embodies and abstracts away some common patterns/behaviours: gen_event, gen_server, gen_fsm, supervisors, logging, distribution between nodes etc. I imagin…
Re: Channels Are Not Enough
#4Remember that one of Go's primary stated goals is "speed of compilation"[1]. Simplicity and ease of learning are paramount, and it's easier to learn a language where any chunk of code basically follows the same rules as any other.
Re: Channels Are Not Enough
#5Yeah it seem channels are basic primitives. Kind of a like a class in OO programming. Just like Erlang has explicit processes and message sending primitives So it is pretty simple and concise at that level. In order to build large systems there is OTP (or e2) that embodies and abstracts away some common patterns/behaviours: gen_event, gen_server, gen_fsm, supervisors, logging, distribution between nodes etc. I imagin…
The problem (which the article touches on) is that you have to resort to interface{} to make things reusable since Go doesn't have generics. So you have to pick between using a library (which will handle edge cases better) or compile time type checking.
Re: Channels Are Not Enough
#6Keep in mind that, were I to write this again today from scratch, there are a number of things I would do differently (since I started it as a relative beginner expanded on it as my familiarity with Go developed, it's grown to be a bit over-engineered in places). But I still think it's a worthwhile example in this discussion.
For concurrency, I wouldn't say that what OP is trying to do is going to be easy in any language, because OAuth in general kind of sucks[1] the Twitter API itself has a number of quirks that make it cumbersome in general, irrespective of language[2]. That said, Go was by far the easiest to work with here, because channels allowed me to abstract the pagination and the rate-limiting in a way that it would be invisible to all callers, but "magically" handled behind the scenes.
Without going into too much detail, I can see that the way OP has designed his code looks a bit cumbersome. That said, while it's a reasonable way of approaching it, I don't think it's actually the best approach in Go given the language's idioms.
One other thing I want to draw attention to is the use of the general-purpose function for issuing a GET request to Twitter, and how that is shared among the various functions that use it to return values of varying, but known, types.
I don't want to use the word "generic" here because people expect a certain thing when they hear that word, but I will say that this function is (A) general-purpose, and (B) type-safe - it involves no type assertions, and the functions all return concrete types instead if interface{}.
[0] https://github.com/ChimeraCoder/anaconda/
[1] Don't get me started on this
[2] I've written client libraries for Twitter in a few different languages, so I actually have a reasonable point of reference on this - at one point, it was my personal "hello world" for testing out a new language.
Re: Channels Are Not Enough
#7This Go client implementation https://github.com/pebbe/zmq4 by Peter Kleiweg also includes all the examples from the online zeromq guide which is great.
I know it's not a pure ago solution but the OP does mention that
'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.'
I don't know, maybe I'm missing the point of the article.
Re: Channels Are Not Enough
#8Earlier quoted context omitted.
The problem (which the article touches on) is that you have to resort to interface{} to make things reusable since Go doesn't have generics. So you have to pick between using a library (which will handle edge cases better) or compile time type checking.
How about replacing certain compile time type checks with smoke tests and runtime assertions, or unit tests?
Re: Channels Are Not Enough
#9Wouldn't a library like zeromq address the complications/shortcomings the OP highlights in his article, when working with Go channels on a regular basis? Using the 'inproc' for message transport with zeromq should give similar performance to pure go channels no? This Go client implementation https://github.com/pebbe/zmq4 by Peter Kleiweg also includes all the examples from the online zeromq guide which is great. I kn…
Re: Channels Are Not Enough
#10It's funny that OP uses Twitter as the case study at the end. I wrote what was then the first (and think still the only) Go Twitter client library that works with v1.1 of Twitter's API[0]. It implements automatic rate-limiting/throttling behind the scenes, and it returns values of concrete types (not interfaces) ready for immediate use. Keep in mind that, were I to write this again today from scratch, there are a num…