5 ms·
>For instance, I'd like to write a function that takes in a channel and returns a channel that has been turned asynchronous, by running a goroutine that manages
by zemo 14y ago
>For instance, I'd like to write a function that takes in a channel and returns a channel that has been turned asynchronous, by running a goroutine that manages a queue and doing some other things above and beyond what a merely buffered channel does, but I can't do that correctly and safely.
see here: http://gowithconfidence.tumblr.com/post/31426832143/stacked-channels http://gowithconfidence.tumblr.com/post/31426832143/stacked-...
the trick is to make a channel of buffer size 1, then when adding to it, simultaneously try to read and write from that channel using a select statement. Only one will ever be ready.
You could also do something similar really horribly with interface{} but that's almost always a code smell: https://gist.github.com/jordanorelli/3668150 https://gist.github.com/jordanorelli/3668150
I probably wouldn't do that in production code.
Either way, generics in Go remains an open question.
- jerf 14y agoThat's simpler that what Erlang does (you need some code for the time backoff, and while I think Go can do it it is inherently the sort of code that ends up a complicated mess of cases that, if I could lock it behind a function, would be very well abstracted away for the user), but it is the basic idea. The problem is, you have to copy & paste those lines of code for every type you want to do that with; you can't vary that code on "Thing". In this case the fact I'd have to use interface{} isn't a code smell, it's a language smell. Looking in two different "directions" from Go, that's trivial to implement as a single Thing-agnostic function in the weaker-type system Python (gevent queues have similar enough semantics for this to be a fair comparison), and it's trivial in stronger-type system Haskell (also similar enough semantics with TChan to be fair). Also I note you did not return the chan for the user to do with as they like, abstracting out the mechanics from the task, but have a hard-coded "join" function in there. You can easily take in a function to "do something", but you won't be able to do anything with the resulting value, not even return it, unless via inteface{}. (Which makes me cringe every time I type it.) Again, to be clear, I'm not trying to dump on Go here; there's a lot of things to like about it, especially its infrastructure. But this is by far my biggest pain point with it personally. YMMV.
- zeeboo 14y agoYou can abstract the channel operations behind interfaces and regain type safety. Inspired by the sort package, I wrote http://thegoods.biz/broadcast http://thegoods.biz/broadcast for doing broadcast type patterns safely. To use it you implement two trivial methods on a channel type and away you go, single producer multiple consumer channels. I think there are clever solutions to these types of problems that have yet to be explored because most of the focus is on what Go lacks from other languages.
- jerf 14y agoIt concerns me that Go has apparently built up such a community of people who insist that there aren't any problems here and you just need to learn the Go way to do it, which nobody quite knows yet, and doesn't quite meet the bill when demonstrated, and seems to require an awful lot of copy & paste boilerplate even so. I don't think that solution addresses my concern, which is that I want to be able to take a channel, and return a modified channel. You can't do that by "wrapping behind an interface", because once you return anything other than another channel you've lost, because you can't "select" on anything other than a channel. You can't say "Oh, I'll wrap the select behind something", because there's no way to compose two selects together; if I want to select on this channel and that channel I must have them both in hand, as channels. So if I want to factor out a particular strategy for managing input on channels, it's just impossible as it stands now; the type system is sufficiently limiting that we can see that that is impossible to write such functionality. (I haven't gotten around to coding this yet, since I've been taking a break, but the actual solution I'm planning is like this: in the library; func DoSomethingGeneric (interface{}) (interface{}) { blah blah blah lots of reflect probably return newThingy } in the module using the code: func DoSomethingSpecific (Thing) (Thing) { return DoSomethingGeneric(Thing).(Thing) } } I'd make it correct by construction, but that's annoying. Annoying is bad at scale, it means people do the lazy thing instead of the right thing.) Further, I don't see any way to abstract out the pattern that you do have in hand; you wrote it, and if you want to stick a new type into it, you'll have to write quite a bit of code again. It's too soon for the community to be this dogmatic about how Go has an answer to everything, when it plainly doesn't. And let me underline this: I'm not complaining that it doesn't have an answer to everything; it's young. I'm complaining that it's too early to be so dogmatic. This is the biggest turn off to me about the developing community. I keep thinking maybe I'm just spoiled by Haskell or something, then I remember; I can do this in every other language I know in one way or another. In the dynamic languages, it's not any more type safe than anything else, but it works. In the stronger languages, I can get this done. Only Go has has a type system that is strongly typed, but forces me to bypass the system to get it done. (Perhaps C, though that's contingent on so many things it's hard to construct a fair comparison. One must first build a fair amount of structure to even approximate the problem I'm having with Go here.) And it's not like I'm a stranger to programming under very strong restrictions. I like Haskell. (Also, I am aware that "the community" who is saying this is not everybody; those who are not should probably work on telling those people to tone it down a bit. And broadly speaking, I actually do like Go; this conversation is focusing on my two biggest pain points and is not representative of my full opinion.)