14 ms·
Generics aren't ready for Go
- whatshisface 8y agoMaybe a Go programmer can enlighten me - without generics, how can you have data structures implementations that can contain more than one type? Do you have to have one linked list implementation for every type in your program? Do you have to abandon type checking by using an equivalent of void pointers? Or is the type system smart enough that you'd never need generics in the first place?
- nicoburns 8y agoMy understanding is that the standard library containers implement generics via special compuler magic, and everyone else is using `interface {}`, which is the equivalent of a void point or "any" type in Go.
- emersion 8y agoIt's not strictly speaking "standard library containers", but rather "builtin containers".
- zeveb 8y agoIt's really not the equivalent of a void pointer, because interface{} is still typed, and you can still interrogate its type, and the runtime prevents you from using it as any type other what it actually is. So it's far safer than a void pointer, although it can crash the program — but cleanly (because of the aforementioned runtime checks).
- emersion 8y agoYou'd have to use an equivalent of `void *` (for Go, it's the empty interface: `interface{}`). However in 99% of the cases the builtin slice and map data structures are enough.
- kkirsche 8y agoI believe this is done using protocols / interfaces where you declare a shared api of the objects
- pjmlp 8y agoThey make use of code generation like early MS-DOS C++ compilers, check Kubernetes source code.
- vbezhenar 8y agoTime for Go++?
- pjmlp 8y agoNot at all, generics like CLU (1975) does, would already be better than the current state. http://www.pmg.lcs.mit.edu/CLU.html http://www.pmg.lcs.mit.edu/CLU.html
- atilaneves 8y agoIf I had the time, I'd love to apply the C to C++ diff on top of Go (templates, overloading, etc.), release it as Go++, and watch the world burn. Just for the lulz.
- Svip 8y agoYou generally try to design your list so it contains types with common methods by using an interface (not the any type interface{}, mind). You could have a list (slice or map) of io.Writer, where it can contain any type that implements Write([]byte) on itself.
- kasey_junk 8y agoFirst go does have generics. It just doesn’t have user defined generics. But to answer your question go has really mediocre support for a wide variety of problems. Some that burn me a lot is support for future/promises and support for modern lock free algorithms. So you end up either writing non-optimal replacements, losing type safety or in some case code generation is used.
- emersion 8y ago>Some that burn me a lot is support for future/promises This doesn't make sense in Go. Nothing is asynchronous in Go, everything is blocking. You use goroutines to execute multiple tasks at the same time. That's a big part of what makes Go simple: it's a lot easier to understand sequential code than spaghetti callbacks and promises (it's somewhat similar to async/await in the JavaScript world).
- kasey_junk 8y agoYet open up nearly any large golang codebase and you’ll find a channel being used to return a single answer response in the future.
- emersion 8y agoWhat's wrong with that? Go has channels thus it doesn't need futures/promises.
- kasey_junk 8y agoSome problems are more simply modeled as futures/promises than csp. Go’s unsophisticated type system makes it difficult to write a good standard generic data structure library such as a future/promise library. That leads to people either writing a poor replacement, not using that style, or losing type safety. This is precisely what you would predict upon learning golang doesn’t have user defined genetics & ive had it bite me more than once in real projects.
- 8y ago
- dana321 8y agointerface{} is the equivalent of C++17's std::any, of which you can put anything including vector (slice) and maps. If you really want high performance with many different types of a function, its a case of copy-paste-modifying your code. Its a language that is straight-forward, its the antitheisis of tmtowtdi.
- j16sdiz 8y agoYou use an interface. Golang use duck typing. It is very flexible and very simple. (Some times too simple)
- kuschku 8y agoSo how do I make e.g. a TreeSet of something, put my elements in, and get them back out as the same type, without casting?
- jstimpfle 8y agoGo has a kind of generics that also maps cleanly to machine-level generics: interface{}, which is like void* in C. Whereas all the other kinds of generics, I believe, can't offer this quality. They require a lot of machine code instanciations (like C++'s template system). Or at least, in the case of virtual functions ("dynamic polymorphism" with VTables), they cause more brittle abstraction boundaries. Think how in C++, when definining a class, you need to expose a lot of internal details in the header file -- list all the private member functions and fields, etc. This has lead to the so-called PIMPL idiom which is exactly what you do in Go or C.
- pjmlp 8y agoYou don't need to expose any internal details on other languages that make use of generics. Even on C++ this is be eventually a thing of the past, after modules get finally adopted. Using how C++ currently does as argument against generics is a pretty weak argument, given the various ways to implemente them since CLU and ML introduced generic programming into the world.
- jstimpfle 8y agoLayouts of separately compiled classes/structs must still be exposed to the compiler. You can't hide layouts away, they are part of the interface. With all the disadvantages that dependencies bring. > Using how C++ currently does as argument against generics is a pretty weak argument, given the various ways to implemente them since CLU and ML introduced generic programming into the world. I would be interested to know how you think the problem of tighter coupling (a.k.a dependencies) is solveable, because I don't see a solution. For example, I'm pretty sure that typeclasses in Haskell are implemented with either of those two approaches I've mentioned depending on the situation. (Maybe it's possible if we require more information for the linker? I haven't thought through this.)
- pjmlp 8y agoExposed to the compiler doesn't imply exposed to everyone else to see. It is solvable by not sitting in an ivory tower using C++ and Java as the typical examples why Go won't get generics, and instead engage with generics friendly communities.
- weberc2 8y agoYeah, you have to either give up type safety (Go's "void pointers" retain runtime type information, so it's closer to a Python object than a void pointer) or you have to write each implementation. In the case of linked list, that's not a big deal: `type List struct { Next *List; Value int}` and Go comes with a handful of useful generic types (slices, arrays, maps, channels, etc). It also has interfaces and closures, so you can generally go a long way without generics. That said, there are still cases where generics would be useful; however, a lot of the people who complain about generics missing from Go tend to exaggerate the extent to which this is a problem, "You can't ship software in a language without generics!". In the case of Go, you have something like 97% type safe code compared to the many, many successful Python and JavaScript programs that ship with 0% type safety. And lastly, one thing that you can't really appreciate without trying Go--the lack of generics/expressiveness and general simplicity of the language largely means everyone writes the same boring, predictable code, which means you can pretty much pick up any project on GitHub or your own code from years ago and understand it almost immediately. This isn't to say that generics aren't worth it; only that the debate kind of sucks because one side is ignoring that rather significant point.
- latronic_notron 8y ago> "You can't ship software in a language without generics!" Isn't this is a strawman? Most arguments in favor of generics in this thread and elsewhere are well informed and people just want safer code... As you said, you can already have generics using unsafe solutions. Some built-in types have generics. Most people just want this type safety. interface{} does feel like a temporary and clunky solution for people used to generics. > And lastly, one thing that you can't really appreciate without trying Go--the lack of generics/expressiveness and general simplicity of the language largely means everyone writes the same boring, predictable code, which means you can pretty much pick up any project on GitHub or your own code from years ago and understand it almost immediately. I don't get this argument. Why are generics more complicated than other features? Has this hypothesis been tested? I personally find that using generics is way easier and faster than interface{}, Reflection or code generation. Also simpler and less error-prone than features from other languages like inheritance, operator overloading and unbounded coroutines.
- rebeccaskinner 8y agoInterfaces help a little bit. You can't really build re-usable data structures without falling back to `interface{}` and then incurring a performance hit from using reflection to get a well-typed value back out; but you can at least make your bespoke structures very marginally more reusable by defining interfaces ad-hoc.
- weberc2 8y agoTo be clear, you use cheap type assertions to get a well-typed value back out. You can use expensive operations from the `reflect` library to do other things, but not to get a well-typed value back out.
- rebeccaskinner 8y agoLooking at some benchmarks it does look like newer versions of Go at least have pretty reasonable performance for type assertions. That makes the situation a little less bad, but doesn't negate the general ugliness of having type assertions every time you want to get a value back out of a generic data structure.
- weberc2 8y agoFully agree; dealing with `interface{}` is generally pretty tedious.
- robmccoll 8y agoAs many others have stated, there are options. In the linked list example, you could use: - container/list.List which uses its own Element with internal pointers and interface{} for values - write a type-specific implementation (not generic, but no runtime type assertion) - write your own implementation using your own node / element interface type (maybe your list is generic to types that support io.Writer - generic for some use, but if you need access to specific types, you're back to runtime type assertions) - write your own interface{} implementation (constantly needs runtime type assertions) - use code generation (maintenance is harder, potentially non-standard tooling / build steps, but hey - no runtime type assertions) - use a slice instead of a list (Go's version of vectors / dynamic arrays) - still requires some implementation, but the language has a lot of built-ins that make this easier. Depends on use. If you are doing a lot of insertions in the middle, this may suck, FIFO may suck and you need to be careful about not doing append()-shift and effectively leaking memory, LIFO this is dynamic and gives you good cache locality. Up shot is no-runtime type stuff and at least the slices themselves and the built-ins are generic.
- u320 8y agoThis article highlights very well why designing a programming language without generics is a mistake. Adding it after the fact is not trivial, especially if you have high standards wrt simplicity and non-redundancy.
- jstimpfle 8y agoYou're implying that there is a better design that has generics and caters to the same programmer folks. But you don't show what that design is. The OP didn't imply there was one.
- apta 8y agoD, Rust, C#, ML, Delphi, etc.
- jstimpfle 8y agoI haven't used all the other ones, but "Delphi" really made me crack up. I used it for 6 months before I quit my job. It's a mess, junk after junk added on a pile of junk, only surpassing the junk-adding badness of C++ by also having this broken standard library that's somehow required to write any type of software (because the simplest thing, C-like pointers, exist but are really not nice to work with). The task that lead to my decision to quit was to write a data serialization systems for datastructure that I didn't know in which version of junk they were expressed, by interfacing with the broken standard library. The serialization system was to replace another serialization system that somehow didn't quite work. No wonder, it was broken code, and I couldn't see a way to write non-broken code to solve an unsolveable problem. What's nice about Delphi is that the compiler is quick and it has a beginner-friendly IDE with a visual GUI creator (no selling point for me). That's about it, AFAICT.
- apta 8y agoI was referring to generics systems that don't suck.
- 8y ago
- alexandercrohde 8y agoI don't understand how not having generics is at all acceptable. But maybe that's because I come from a functional programming perspective.
- dana321 8y agousing interface{} and reflect is good enough for the many problems of using X datatype
- mixedCase 8y agoOne of Go's tennets is "clear is better than clever", followed by "reflection is never clear". So no, idiomatic Go is not about using reflection, it's what we have to resort to because the language is so limited.
- dana321 8y agoWe're talking about simple reflection here, pass in the value, infer the type and cast to that type. Most people are totally confused by generics, i personally don't have a problem using them or not. At the end of the day, its just template metaprogramming.
- aikah 8y agoNo it is not. What's the point of a compiler if you check types at runtime? It's just that a lot of things in Go weren't carefully designed and now the price of adding something to the language is the price of dealing with technical debt. For instance Go has a form of exception (panics), returning errors is purely a convention. But panics aren't very good at exceptions either.
- dana321 8y agoWell, what was the point of adding std::any in C++17? Generics aren't a cure-all, they merely duplicate code and change the type. Its not much better than copy-paste and replace the type names.
- andy_ppp 8y agoI keep thinking they could add macros instead but I guess the C++ version is too much history for them to be associated with. It would basically be like code generation at compile time, except much cleaner than the current, version-specific mess of tools.
- candiodari 8y agoThey have macros. Sort of. Search "go generate".
- andy_ppp 8y agoIt looks gross. Why not quote and unquote - it makes it so much easier to reason about...
- aikah 8y agoThis isn't a macro language. It relies on an external program that the developer needs to write himself at first place. "go generate" just facilitates the execution of a third party program. It does nothing more, and doesn't even do it automatically when compiling a program.
- emersion 8y agoMacros are another can of worms. Even if they're AST-aware like in Rust, you can do very complicated stuff with them and they are very hard to read/write/debug. This would kill the advantage that it's very hard to write obscure Go code.
- heavenlyblue 8y ago>> his would kill the advantage that it's very hard to write obscure Go code. But it's very easy to spread that Go code into tens of Kloc. The amount of error handling and if constructs make me feel as if I am readying assembly: predictable AF, but it doesn't help because the volume of the code is huge.
- 8y ago
- orbifold 8y agoAs a physicist I find out of context references to physics pretty annoying. No go modules are not like a grand unified theory, nor is any other go package management solution like general relativity.
- bunderbunder 8y agoJust enjoy that these kinds of references give you so much latitude for interpretation. For example, in the absence of any practical exposition demonstrating that the module system solves problems that other systems don't, you can quite comfortably (and cynically, sure, but please let me have my fun) choose to interpret the analogy along these lines: General relativity is well-established, reasonably well-understood, and is essential to making a sizable chunk of the modern world (e.g., GPS) work. Whereas nobody's been able to demonstrate a working GUT yet, so currently its main practical use is as fodder for books and TV specials.
- alexandercrohde 8y agoThis reads like sour grapes. Basically, this is trying to spin "Popular language missing essential feature" into "But what if it's because they're braintstorming something EVEN BETTER???" Well, if they're brainstorming something better, then I'll wait to use your language until you solve all the basic problems first. Plus I think the language-obsession is usually cargo-culting and signaling. All good engineers I know use and enjoy several languages. The hipster/all-talk/buzzword engineers are the ones who insist on prototyping garbage in a new language every 6 weeks and dropping it entirely thereafter.
- throwaway415415 8y agoLack of generics is a feature imo
- grumpydba 8y ago> Well, if they're brainstorming something better, then I'll wait to use your language until you solve all the basic problems first. Yet people can write distributed databases, monitoring tools, dns/DHCP servers in go. ANd they deliver stable and performant solutions with thousands of institutional users. How come, if the basics are not solved?
- rowanG077 8y agoThat is a meaningless statement. You can do anything in (almost)any language that doesn't mean the basics are solved.
- mirekrusin 8y agoThey did pop up in short period of time and go projects are generally considered quite stable - how can you achieve those without "basics being solved"? IMHO basics is precisely what they did solve exceptionally well.
- weberc2 8y agoThe parent should have said, "Go is regularly used to ship..." instead of "Go can be used...". The fact that Go backs all sorts of complex, interesting software testifies that it has solved the basics extrememly well, and if you're going to argue for a definition of "the basics" which doesn't respect shipping software then your argument is self-defeating. "Generics" isn't an end unto itself, after all.
- spion 8y ago> Go strikes me as one of the most conservative programming languages available today. It’s small and simple, and every detail is carefully thought out. This article is wrong in many ways, but I thought I'd point out this particular one. There are many really weird warts in Go, in fact its about average in "wartiness". Here is one example https://dave.cheney.net/2017/08/09/typed-nils-in-go-2 https://dave.cheney.net/2017/08/09/typed-nils-in-go-2 Go biggest advantage isn't the language, its the decent documentation and standard library design. The language is a bit mediocre. I wish the Go community accepted this and moved on - a mediocre language with good documentation and well done standard library is still an acceptable contender since so many other languages get those two wrong.
- throwaway415415 8y agoSucks for you, considered very good by plenty of other people who use it daily.
- rebeccaskinner 8y agoI use Go daily and I agree with the general sentiment that it's a janky language full of warts and could really benefit from features like generics.
- kasey_junk 8y agoSame
- throwaway415415 8y agoMaybe go back to java or c++? I'd rather have less people complain about a feature I don't want in the language.
- rebeccaskinner 8y agoI'd love to get away from Go again, but unfortunately it's the hot thing that people see on your resume and then they don't want to talk to you about anything else. I'm very concerned that in a few years it's going to be the terrible low-paying boring thing that people see on your resume and don't want to talk to you about anything else.
- gok 8y ago> The constraints imposed by the lack of generics (and other things Go lacks) breed creativity Uhg such programming language Stockholm syndrome. You could apply this fallacy to any feature. The lack of modules and a performant garbage collector also bred creative solutions in previous Go releases, but that doesn't mean that adding those was a bad idea.
- emersion 8y agoAs said in the article, solutions to these problems have now been implemented. These solutions _feel_ very Go-ish. Modules are an elegant solution. Adding them was a good idea. Until we find an elegant solution for the generics issue, it's better not to have them.
- bunderbunder 8y agoI realize I'm not the audience here, but still -- As someone who isn't terribly familiar with Go, most of what I'm seeing in this article is the shady corners I can't see into. The generics one, I've seen plenty of pixels spilled on, and I've come to accept that I won't really grok the debate unless I spend some serious time programming in Go. What about the module system, though? Can anyone explain or share an article on what's so great about its module system?
- throwaway415415 8y agoExactly. If you can't get rid of your favorite paradigm (which seems to be generics for some reason in this thread) then I guess stick with the language you are already using and don't try to wrap your head around other languages?
- tebruno99 8y agoBeen using Go for 4 years. I totally agree. It sucks to have to use your brain to think about alternative ideas on how to do something. However, I’ve come across much much better solutions to my problems than I would have if Go offered a crutch to my flawed thinking.
- aikah 8y agoThe problem is the solution is often to make the compiler ignore types all together and use interface {} wholesale, then test interfaces with type assertions. If Go had a least unions, it would be a bit less painful to describe a range of finite types while keeping things strictly typed in functions and methods. Unions are a limited form of type polymorphism in a garbage collected language.
- weberc2 8y agoI'd be disappointed if Go went for unions instead of full-on Rust-like enums, but I agree with your general point.
- yawaramin 8y ago> I’ve come across much much better solutions to my problems than I would have if Go offered a crutch to my flawed thinking. Any example where you have a better solution than using generics?
- fauigerzigerk 8y ago>Have you ever seen someone write something to the effect of “I would use Go, but I need generics”? Perhaps we can infer from this that many of the people who are pining after generics in Go are not, in fact, Go users. This is the sort non-adhominem adhominem attack that makes these debates so tedious. Obviously, someone deciding not to use Go for lack of generics after giving it a serious try would end up not being a Go user. Does that invalidate their opinion? The logic of this argument is strikingly cult-like. Any criticism coming from non-adherents is automatically disregarded on the basis of it coming from non-adherents.
- klmr 8y agoIn addition there are plenty of people who do use Go yet still criticise its lack of generics. But apparently these are not “real” Go users?
- Foober223 8y agoAn algorithm or data structure may be applied to various types of data. There's various ways to handle this. Macro expansion, generics (basically equivalent of macro expansion but as a language syntax), or losing types: void pointers, duck typing, interfaces. Go puts it's head in the sand and and handles the problem like it's 1970 with the "void pointer" way of thinking. That's fine if you're using a dynamic language (ie python, lisp) and firmly decided your trade offs with regards to types and performance. But if you elect to use a statically typed language, it would be nice to reap the benefits. Modern C++ is still the only way to go for serious software. Rust maybe in the future as the compilers improve. Go is a no no-go.
- grumpydba 8y ago> Modern C++ is still the only way to go for serious software. Please define serious software.
- jstimpfle 8y agoI don't speak from experience with Go, but a simple type assertion at an interface boundary should normally not be noticeable at all. Where performance matters, there you usually do not have parameteric types or similar. Have you measured anything?
- atilaneves 8y ago> they feel that generics are a good fit for this language Or that it's ludicrous for any statically typed language to not have generics. > It’s small and simple, and every detail is carefully thought out > Nearly all of Go’s features are bulletproof > my opinion are among the best implementations of their concepts in our entire industry Uh huh. > You could write a book called “C++: the good parts”, but consider that such a book about Go would just be a book about Go Or it could be one-liner: "easy concurrency". > simplicity and elegance are now the principles I optimize for Doesn't everyone who cares? The problem is that elegance and simplicity, like beauty, are in the eye of the beholder. To me, generics increase elegance and simplicity. > If you’re fighting Go’s lack of generics trying to do something Your Way, you might want to step back and consider a solution to the problem which embraces the limitations of Go instead So pretend it's the 70s and use void* (interface{})?
- cannabis_sam 8y agoIt’s weird seeing all this post-hoc rationalising when there is a perfect explanation for why go doesn’t have generics: Rob Pike didn’t bother to look into any of the research into type theory and programming language technology. Hence his understanding of types were restricted to Java and C++ and similar (whose type systems are an abomination), and he could not separate subclass polymorhism with inhertance from parametric polymorhism. But more important, what it says is that types are the way to lift that burden. Types. Not polymorphic functions or language primitives or helpers of other kinds, but types. That's the detail that sticks with me. Programmers who come to Go from C++ and Java miss the idea of programming with types, particularly inheritance and subclassing and all that. Perhaps I'm a philistine about types but I've never found that model particularly expressive. My late friend Alain Fournier once told me that he considered the lowest form of academic work to be taxonomy. And you know what? Type hierarchies are just that. https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html https://commandcenter.blogspot.com/2012/06/less-is-exponenti... I mean he’s openly contemptous of the academics who do research in his field, while wildly mistepresenting their work. But people eat that shit up, because ”OMG it’s Rob Pike” instead of actually discussing the underlying issues. Yes Rob, you are a philistine when it comes to types.. (or at least were)
- jstimpfle 8y agoOr maybe the academics and type theorists are philistines about the software that runs the world and their arguments have mostly been about hand-picked toy examples? Maybe Mr. Pike actually has some well-deserved reputation when it comes to real-world software and engineering projects that are about handling large scale data in real time?
- apta 8y ago> Maybe Mr. Pike actually has some well-deserved reputation when it comes to real-world software and engineering projects that are about handling large scale data in real time? What are the credentials to back this up? Otherwise, the languages he makes fun of actually are used to deliver large scale systems in real time. Google is built on C++ and Java, so are most of the other top tech companies, not to mention banks and HFT firms.
- smolder 8y agoThe way he describes Go's existing feature set as unwavering perfection is disappointing. No language is perfect except in heavily constrained context. They all make trade offs. GC is itself a compromise and so it follows that Go is not the one true language.
- fastbmk 8y agoGo programming language is designed for developers with mediocre level of intelligence! The original language authors talk about that all the time, but nobody listens. If you bring Generics to Go, most Go developers will be forced to switch to another simplistic programming language, like Basic. [https://i.imgur.com/Y39gsPI.png https://i.imgur.com/Y39gsPI.png]