Hacker News new | past | comments | ask | show | jobs | submit login

There's no generalized solution to every generic problem. The "cast to interface{}" is the closest to a linear mapping of generics, but if you're reaching for that all the time, you're doing it wrong. So the only sane answer is, "it depends".

The only use case that I have encountered that is essentially impossible in Go is the "generic data structure". Mind you, that's a bit of a big deal, even if it covered over by "generic" arrays and maps (which, further, does cover over a lot of the cases), but it is also the only case where it is actually a problem. Despite the fact Go is not functional, like, at all, I still find myself using my functional training in minimizing the surface area of an "object" as much as possible incredibly useful when programming in Go. I think if I were only an OO programmer trying to come over to Go I'd have a much harder time of it.

Most of the rest of the time you can solve your problem by asking what the code is really trying to do, pull that up into an interface, and carry on. A substantial portion of the rest of the use case can be covered by providing wrapper objects that compose in another object, probably using an interface as the composition point.

I think in practice, about 80% of the problems that people trying to jam generics into Go are encountering are because they are trying to program C++, Java, or C# in Go. Despite their substantial superficial similarities, Go is not any of them, and idiomatic answers differ substantially. Let me rhetorically underline that... Go really looks like a Java or C# clone if you just read down the bullet points, but there are enough important differences that it's a substantially different experience to program in it. Trying to program Go as C# is only slightly less frustrating than trying to port FP idioms into Go (which is a complete waste of time). The remaining 20% are real problems that Go hasn't got a good answer for beyond duplicating code.

Now. All that said, despite the fact that people not used to idiomatic Go are significantly overstating the problem that is the lack of generics, it is a problem and were I in charge, I'd be trying to work something out on this front. (I actually have a proposal I've probably put about 4 or 5 hours of thought into. In defense of the Go developers, this is a nontrivial problem when you stop just waving the word "generic" around and start trying to seriously create an implementable suggestion, accounting for all the use cases, grammar interactions, semantics, etc.) My best argument is that for a language as mature as Go, this is embarrassing: http://golang.org/pkg/container/ Those are the "generic" containers in the standard library that ship with the language.... all three of them as of this writing, plus array and map. At this point that ought to be significantly richer.

(So, that ought to just about piss everybody off...)

Oh, I ought to add for context that I'm actually pretty fluent in Haskell, and my primary work programming language up to this point have been dynamic languages (Perl, Python, etc). So it's not like I'm not comfortable with generics or incapable of understanding how to use them or anything. If anything, I dare say my openness to other answers and then finding ways to express them in Go may be part of why this doesn't bother me too much. There are other options, most of the time, and they are not generally "compromises", either... they are often perfectly sensible options, or even better options than are available in other languages on a bang/buck basis, such as the trade for making composition very easy and inheritance something fairly difficult.




Talking about how to implement generics generically isn't really responding to my question. The original post had questions about how to implement specific concurrent constructs like pipelines, futures, and so on. So the question is how do you handle concurrency in Go? Are we missing important features that should be part of the language or standard libraries?

Some of these may be one-off generic functions like append() that could be added to the language without adding full-blown generics.


I know this is going to sound like an evasion, but the answer is that idiomatic Go doesn't involve pulling in patterns from other languages, but using ones native to the language.

Futures I can be specific about, though. You simply don't use "futures" in Go. Futures (as the term is used by most languages) are a hack around missing concurrency constructs, and in Go, they aren't missing. Use channels instead. This covers rather a lot of patterns from Javascript and the weaker languages, actually... you don't port them, you simply don't use them. They aren't that appealing once you learn the native idioms, which are, generally, quite a bit better.

Putting a "future" library up on /r/golang is a pretty common occurrence... but they're so trivial they're worthless. It's harder to "use" a future than it is to just do thing the future library is doing.

For pipelines, you just "do" them... you don't set up some declarative pipeline, you just... program them. Sort of like how in the Python world they prefer the for loops to map statements? Same thing, really... if you want a pipeline, just hook things together manually. They may miss out on some abstraction, but, honestly, in most imperative languages I'm underwhelmed by the concept of really generic pipelines. Haskell's making some progress on that front and I've actually got an "in the wild" five-stager, but in the imperative world I'm not sure I've ever encountered in the wild some sort of 6-stage pipeline that was better written other ways.

If any major concurrency pattern is missing from Go, it's an explicitly asynchronous concurrency pattern. However, this can be fixed by library code: https://github.com/thejerf/reign


Interessting. I have not done any go. Could you review go in spirit of you beeing a FP guy? Why does go make it so hard?

Im mainly a clojure guy and we generally belive the CPS and FP go together very well. The new interduction of transducers makes this even clearer and it seams to me this is a feature that go should really think about.


In a nutshell, map, reduce, filter, and function composition are all generic functions, in exactly the sense of generic that Go doesn't have. Lacking all those things, trying to do FP in it is a waste of time. Lacking this foundation, most higher-level FP stuff is also a waste of time, unless there is some other path to it. Even if Go some day picks up generics and gets map, reduce, and filter, my guess is that function composition will never be something you can do in Go.

Note that it does have closures, and makes heavy use of them. It just managed to pick up closures without picking up the rest of FP.

I think this generally fits into the spirit of Go being a really good language for working in a larger development environment, where you can't expect everyone to be expert FP programmers. And, honestly, an intermediate FP programmer is sorta dangerous to your source code, in much the same way an intermediate OO guy is. Go does a surprisingly good job of preventing the intermediate guy from messing up your code too much.

To expand on what I said about the principles of FP being helpful to me in Go even so, here's an example: http://www.jerf.org/iri/post/2923 In theory, there's nothing that prevents another OO language from doing that, but without the structural polymorphism that Go has with its interfaces it's so much less convenient that nobody does it, and, more importantly, nobody thinks that way.

In fact, in some sense I'd say Go is inspired by CSP, but to the extent that CSP involves the creation of these complicated networks of data flowing around, it doesn't really do that. On the other hand, I'm not convinced that's a very practical way to program... complicated networks just become one more source of "magic" in a program. Using CPS-esque tools to make it easy to connect components together is itself pretty powerful.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: