Hacker News new | comments | show | ask | jobs | submit login
Changes I would make to Go (sitr.us)
113 points by jaxondu 33 days ago | hide | past | web | 123 comments | favorite



> First, functional programming is particularly difficult in Go. In fact the language discourages functional programming.

Then it seems that Go isn't the language for you. With that Go nor any language, unless intended, is suppose to be a one-all solution for every problem. We can accomplish a majority, if not all, problems in a language, but this shouldn't assumed that a language is intended to do so.


While I understand the argument for simplicity and agree with the premise in most cases, I find it pretty hard to argue for this code:

    ys := []byte{}
    for _, x in xs {
      ys = append(ys, f(x))
    }
    
over something like this code, which is more obvious, less error-prone, and, though it relies on an additional concept, it's an extremely broadly-known concept:

    ys := collections.map(xs, f)
I don't think a proper collections library would require very invasive runtime changes -- though, once you start down this path, you and up at "but what if `f` returns `(myType, error)`, and then you're wishing for Option/Maybe types (which is another feature that I believe Go should have implemented, but is more obviously outside of the apparent mandate).

EDIT: It would make static analysis significantly more complex too.


Go can't do this, because you can't define `map` as returning "a collection of whatever `f` returns".

If they build a collections API like this now, without generics, and they then add generic types later, they will be in the same position Java found itself in - lots of painful API migrations.

While the generics debate is legendary in go, it does still seem very much like the intention is to eventually include it. Given that, I think it makes perfect sense to wait to introduce more special cases (like `append`).

In the meantime:

    func Map(in []interface{}, f func(interface{}) interface{}) []interface{} {
    	out := make([]interface{}, len(in))
    	for i, v := range in {
    		out[i] = f(v)
    	}
    	return out
    }
:)


But there is literally the `map`, `slice`, `chan`, and `append` which are generics.

The fact that append exists and the language would be extremely convoluted and inefficient to use is a testimony to how useful generic programming is.


> While the generics debate is legendary in go, it does still seem very much like the intention is to eventually include it.

Yes, when this topic comes up I think it helps to remember that the Go devs are in no way opposed to generics. They have no philosophical "thing" against it, and it's not about "our ideology and where we want to go with Go".

https://golang.org/doc/faq#generics

It's more like... It's complicating the type system and a hard problem to solve. If they do it, they want to do it right, because a main goal is to not get complicated.


It looks like you're making the same point as burke and the original article: Go lacks common-sense features that would make writing safe, simple code easy.


I guess we're agreeing on the fact that Go lacks generics. I don't know that I agree that those makes "writing safe and simple code easy". As we both know, simple and easy are two very different things.

Generics do make a lot of problems easy, but I don't think they inherently make problem solving simple. I absolutely miss them in Go - but I also remember how confused my high school programming teacher and I both were about them.

So far, Go seems to err on the side of Simple, if a choice has to be made. And, so far, the proposals for generics in Go seem to force that decision. I'm glad to see how seriously the Go authors take weighing the design and decision to include them.


Well I guess I misread your comment, then. I had assumed your code sample for a type-unsafe implementation of Map, followed by the smiley, was a recognition of the major lacking on Go, not just of generics but of the ability to operate on collections. I read burke's comment as suggesting a privileged collections library that doesn't go all the way to user-space generics, but perhaps I misread that, too.

I would strongly disagree with the definition of "simple" that you seem to be using. I don't think it's important for a language designed for software professionals to have only features that are easy for high schoolers to understand. It's far more important that experienced developers be able to write a common idiom like map with as little cognitive overhead as possible, that's the meaning of simple that I find valuable in this context.


I happen to agree with most of the points the author makes--that those features would make Go nicer. I think I disagree with the author (and probably you) about the degree to which these features matter. I write a lot of Go code, and the times when I really need those features or feel that those features noticeably reduce my risk of error are few and far between. Go code is not as DRY as Rust or some other languages, but I'm not sure that the extra DRY-ness would make me significantly more productive or correct. If someone wanted to fork Go and implement these features, I'd love to be proved wrong.


No offence but it only seems "more obvious and less error-prone" to you because you likely have experience with functional programming and dealing with maps (typical of functional programming).

There are plenty of programmers for whom this is cryptic, and they prefer an old-school "simple and straighforward" for loop (typical of imperative programming).


This is absurd — this mentality can be used to argue against literally every form of abstraction ever. The entire reason we have abstractions is to avoid writing the same redundant code over and over, with the associated likelihood of bugs due to typos.

What makes map more cryptic than literally any of the abstractions already in that example? Make is abstracting away GC-based memory allocation, indexing is abstracting away pointer arithmetic, and so on. Why are those abstractions fine, but "apply this function to everything in a collection" is somehow impenetrable voodoo?

"Simple and straightforward" often just boils down to "reams and reams of boilerplate code", where catching bugs is hard because it's impossible to notice a slight errors in one out of a hundred reimplementations of the same function.


> There are plenty of programmers for whom this is cryptic

I've never really done functional programming, and map was cryptic the first time I saw it, but it's literally a concept that can be understood by any competent programmer in under 30 seconds - apply a function to every element of a collection and return a collection containing the results.

I don't have any sympathy for programmers who find simple abstractions like this cryptic but then don't try to understand them.


His point is that golang makes it unnecessarily hard to accomplish what really ought to be simple tasks inherited from functional programming ideas. Other languages, like Rust and Ruby, have adopted some of the really simple and powerful functional idioms like Map, Sum, Select, Reduce, etc., whereas golang makes it impossible to abstract away any sort of iteration logic. He even shows how this lack of abstraction power has knock-on effects in the form of dramatically-increased difficulty of parallelism and concurrency.


I don't think the tradeoffs made by Go have been explained in a way that makes sense to people who find value in the techniques and idioms described in the article. I agree, if Go lacked these features because they were consciously traded away for something else of value, then it would only be half an argument to point out that they have value.

It would only make sense to make that point if they were intentionally left out of Go because they were regarded as having no significant value or even negative value. And that, I think, is the widespread perception of why they aren't supported in Go.

We can accomplish a majority, if not all, problems in a language, but this shouldn't assumed that a language is intended to do so.

The programming methods described in the article can be applied to almost any problem that Go is a good fit for. If that's in question then I think it proves my original point — this argument is not about arguing the tradeoffs; it's about whether anything of value was left out.


In Dlang you can do functional programming, although it's not as pretty as a pure functional language.

http://dlang.org/phobos/std_functional.html


OK, go will never have generics (except that it does in "make", "range", "chan", ok whatever...). That's fine with me. But including even just a few suggestions in the parent article would make Go a more approachable language to everybody.

* Pattern matching is intuitive and can be extremely powerful. * It's pretty clear that Null should not exist anymore. * Multiple return values, but no tuples?!

The go designers seem to not have a problem with special cases so why didn't they include special cases for an Option<T> and Result<T,E>, two things that, with pattern matching, would fit right into Go's explicit error checking philosophy.


> OK, go will never have generics (except that it does in "make", "range", "chan", ok whatever...). That's fine with me. But including even just a few suggestions in the parent article would make Go a more approachable language to everybody.

The current position is that the core team will only include generics if they can find a design that satisfies them. Which has sounded a lot like "no, never" but Russ Cox has said that he wants to look into implementing generics again this year.


Just another generic complaint about Go's lack of bloat. It's all completely naive, never understanding why Go doesnt want generics beyond a simple "b-b-but look, the pattern matching of Rust is simple too!" No it isnt simple just because you say it is. It is the opposite of simple. I've read the Rust docs on it several times and I still dont have a clear mental picture of how to read a match statement out loud. "match result with Some(number) .. then do..? But match HOW?" I've been thinking of a clearer syntax/naming for match and in my humble opinion it should literally just be called 'if' and any inconsistency that doesnt align with that be removed from the language. Calling 'match' match is haskell programmers gone wild. Programmers in the real world dont have a clue how to read 'match'


If you have the time and inclination, I'd love to know if the second edition of the book makes it more clear to you http://rust-lang.github.io/book/second-edition/ch06-02-match...


I agree a bit, in haskell for example it is not always easy to figure out the computation order, it is about tradeoff and go looks too much on the simpler side.


I really want to love Rust, but it's so visually unappealing :/ I love how clean Go looks. I know it's vain..


Like all things superficial, the more time you spend looking at something, the more the visual appeal (or lack thereof) normalises to average.

I think one tangibly good thing about Go though is how readable it is and how easy it is to grok, even with all the error handling boilerplate. I'd argue that Rust is also very readable though, and if the features of the language appeal to you I'd suggest giving it some time to get over the visual hurdle.

From a personal standpoint having spent years working in both languages, it's rare I'll choose Go over Rust nowadays purely for practical reasons. I'm roughly equally productive in both, but the end result tends to be much more performant, maintainable and robust on the Rust side.


Thanks for the encouragement!


That must be very subjective, as I have the exact opposite reaction. I mean, there are portions of rust that are dense and cluttered, such as function definitions with the ownership rules, but the content of those functions I find very clear and concise.


To me, Go and Rust are about equally appealing. Rust is more complex to me because it's a lower-level language; Go looks like a higher-level cousin.

I learned from Rust that I dislike curly braces. The language itself seems great conceptually, but I prefer the appearance of languages like Python that drop curly braces. If Rust was developed without curly braces I'd probably be [more] obsessed with it.

Strangely enough, parentheses and square brackets are also appealing. I also dislike writing code where whitespace is meaningful, even though I prefer to read it.

It's just the appearance of curly braces that bothers me.


> It's just the appearance of curly braces that bothers me.

That sounds easily fixable with a different font. Or make your own. :)


These are the changes that if made Go wouldn't be language it is. Go is simple, straightforward if little verbose. To me Go fits perfectly for business apps that I write currently in Java.


I'm not sure - I've been writing Go for 4 years in a production setting, when we switched our API service from Python to Go at the release of Go 1.1. Since then our default language is Go, and I write Go everyday. Things like Generics I haven't been really bothered by.

But where I thought he brought up really good points are

1. nil. He's right compared to more recent languages, nil is awkward. I've been bit multiple times by the 'nil checks sometimes fail.' concept. Option/Sum types are so much cleaner, and having non-nullable types make a lot of things easier to reason about.

2. error checking. My main gripe is when you are writing a process that involves calling multiple functions that could return errors. You then need more boiler plate in order to stay sane and DRY - and I've admittedly bitten myself with the 'err' shadowing that happens sometimes.

I don't think a Maybe type would have made Go more complex, and I think it would have fit in nicely with the 'Zero Value' concept.


2. error checking... I've admittedly bitten myself with the 'err' shadowing that happens sometimes.

This is indeed a problem. It's the same problem with people writing a catch-all exception in Java, then forgetting to write the correct handler later. Considering the Go team's priorities, it's one they should fix!


Go has "defer", which is great. Perhaps it should have a similar "whenever" construct.

    val, err := foo()
    if err != nil
        return err
    vee, err := bar()
    if err != nil
        return err
Would become:

    var err error
    whenever err != nil
        return err
    val, err := foo()
    vee, err := bar()
Static analysis would insert the appropriate check any time err is assigned in the function. Aliasing might be a gotcha, but I'd bet that is a rare case and static escape analysis could maybe catch it and either error, or just insert extra checks.


Maybe/Option/Result types don't work without generics, because you significantly reduce the type checking.


And this is why people have been begging the golang developers to add generics practically since it was conceived. Yes, generics make compiler-writers' lives more difficult. But they can dramatically simplify the lives of everyone else.


I'm not a Go programmer, but from what I understand, things like Go's map implementation in the standard library are usable as if they're generic. Couldn't they add a few more types like this (e.g. Option and Result) in the same way without exposing generics as a language feature?


You are absolutely correct. Go has generics. It just doesn't have user defined ones.

If the language designers thought an Option/Result/Try was valuable they could add it. Just like they could add Futures/Promises and concurrent safe maps if they wanted to.


I program some Go - I believe you are talking about the 'empty interface', e.g. map[string]interface{} The problem with that is that you instantly lose compile-time type checking, and have to check/assert the types yourself at runtime after accessing the map. In a strongly-typed language this kinda goes against the grain, and is a PITA. (Although it still can be useful at times). My 2p.


The point is that a map can be type safe because it's built into the language, and that the designers could do exactly the same with a maybe/option/result feature.


> 2. error checking

What I want? I want to

a) have an option where an unchecked return error causes the program to log and exit.

   error SomeFn(int blah, int haw)
   {
      if(blah < 0 || haw < 0)
        error(1);

      return(bah*haw);
   }

   // program will die here
   SomeFn(-20, 23);

   // program will not die here
   if(SomeFn(-20, 23) != 0)
   {
     // something
   }
b) be able to pass a label to a function to handle errors.

Example

   int SomeFn(int blah, int haw, error oops)
   {
      if(blah < 0 || haw < 0)
        oops(1);

      return(bah*haw);
   }

   int res = SomeFn(-20, 23, crap);
   printf("res =%i\n", res);

   // SomeFn returns here
   crap:
      print("parameters can't be negative");


I think go would actually be a pretty bad match for software that is modeling some sort of business domain. The type system is just not robust enough for it.

What it is good for is software that is about moving bytes around from place to place. Network daemons, web servers, cli tools that interact with JSON/Xml in simple ways.


Let Go be Go, let Rust be Rust, and let Haskell be Haskell. There's no need to try to make Go into Rust; we already have one of those.


>every language is unique

>every language is equivalently powerful

>therefore, we should neither look to one language to improve another

We seem to have made a mistake somewhere.


We didn't do any such thing. You seem to think that I did, based on putting words in my mouth that I never said, nor intended. Your response is therefore a strawman.

Let's try again, shall we?

Some languages are trying to serve different niches than other languages. Trying to copy features from one language to another can be useful. But if you're copying from a language that's used for a different niche, you can ruin the destination language's suitability for its own niche.

What's Go's niche? The original intent was that it be useful for multi-million-line code bases that lived for multiple decades. Cost of compile time becomes a very big deal in that environment. (The original motivator was a 45-minute C++ compile. Multiply that times multiple developers, times multiple compiles per day, times 20 years, and it adds up to real money.)

What's Rust's niche? It's lower-level (C++-ish) code with compiler-enforced safety.

What's Haskell's niche? People are probably going to yell at me for this, but I think it's improved ability to reason about the algorithm.

It is unclear to me that an idea that's useful in one of these niches should automatically be assumed to be useful in another. Sure, if you're used to one niche, and you try to cross over to another, you miss things, but that doesn't mean that having it would be a net win in the other niche.


I have a hard time imagining Go really reaching the niche you've described such that it has a chance at satisfying it. Million line codebases don't appear out of nowhere: the language has to be useful and natural enough that developers want to continue working on a project in it until it reaches that size.

That being said, plenty about Go seems to make it easier to get there: the lack of reasonable tools for abstraction certainly makes copy-paste programming much more likely, along with the ensuing explosion in LOC.


>It is unclear to me that an idea that's useful in one of these niches should automatically be assumed to be useful in another.

Yes, but you originally asked us to do the opposite: to not modify a language based on the benefits shown in a different language; That an idea useful in one niche should automatically not be assumed to be useful in another.

Which of course is just as baseless as automatically assuming it will be (useful|viable|worth the effort).

Haskell is particularly irratating to see used for that opinion as well, given that is notable for being a research language; a language who at least partially exists to seek out, identify and implement ideas that can be transplanted into other languages, though of course it would naturally take a different shape once integrated.


> Yes, but you originally asked us to do the opposite: to not modify a language based on the benefits shown in a different language

Not quite. I asked you not to try to turn one language into another (that occupies a different niche). We don't need Go to become Rust, because we already have Rust. If Go becomes a better Go by stealing ideas from Rust, that's good. If Go becomes a worse Go by trying to become more of a Rust, that's a net loss.

Haskell... I admit that I was not thinking of it as a research language, where the whole point is to try out ideas. It's become more than that. It's become a "real" (production) language, not just a research language. But I will grant that it (partially) exists to experiment with ideas and export them.


Some language opt for independently compilable module though


One of the primary design principles behind Go is that it be designed to incorporate the best available features of other languages, as much as it is able while remaining simple and easy to learn and use.

If there is a way to incorporate the best features of Haskell and Rust while maintaining Go's current simplicity and ease of use, then it should be incorporated. To that end, the Go core developers have expressed an intent to implement Generics, however they want to do so in a way that does not (significantly) negatively effect the language's simplicity or compile times.

https://github.com/golang/go/issues/15292


I'm not really convinced by the Go rationale on the lack of generics and other things (like sane error handling). Argument from complexity is weak, because literally every other strongly typed mainstream PL has those abstractions by now. It's like arguing that your language shouldn't have loops and functions sometime circa 1970, because they complicate matters over the good old GOTO.

All in all, my impression of Go is that it's a language designed by the same people who wrote the Google C++ coding guidelines (https://www.linkedin.com/pulse/20140503193653-3046051-why-go...).


An open question: has the ship has already sailed on generics in Go? That is, is there too much Go code out there written without generics to ever incorporate generics after-the-fact?

I am in two minds; after all, C++ existed for a long time without a workable implementation of templates, and that hasn't stopped the STL from doing quite well.

On the other hand, there were a number of fairly successful generics implementations already done when Go was created, and some of the core developers for Go seem to really have only lukewarm support for the idea (unlike C++, where Stroustrup seemed to support generics enthusiastically well before they appeared).

It does seem to be a very weird thing to bolt onto an already mature language. Some of the less felicitous bits of the C++ standard library seem like they would have been done very differently if templates had worked from Day 1 in the language.


It's absolutely a possibility for Go 2.0. There's a hard lock on Go 1.X compatibility, but per the link in my above comment the Go team is fielding proposals for Generic implementations. I also recommend reading Russ Cox's (Go core developer) HN comment: https://news.ycombinator.com/item?id=9622417


I've read that before. I do regard the conservatism here as carrying a cost: specifically, great rafts of code will be written without generics and the absence of generics will influence other parts of the language.

I'm not an expert in generics by any stretch of the imagination; I timidly implement the occasional template function, happily use STL/BGL where I can, and am amazed at the sort of data structures this lets me get away with.

I do find myself puzzled that apparently no generics system in common use was deemed 'good enough' by the Go team to just clag before an entire language and its aforementioned 'rafts of code' sprang up around the absence of such features... there may be good reason.

But a language that doesn't let me do what I happily do in C++, with type safety, using language features that are over a decade old, is a total non-starter for me. The language may be all the simpler for this, but the code I would have to write would bear the cost of this instead. It's not a win for me, and vague threats that I'll get a vomitous compiler message when I bugger up "make_pair" and hints that the "princess is in another castle" aren't going to browbeat me into accepting a throwback of a language. My guess is that g++'s template error messages are going to be acceptable long before I see generics in Go, if I ever do.


There's a great deal of discussion about Go generics that I linked, and I understand that it's quite a lot to ask anyone to read, so I want to sum it up as best I can:

The Go team wants generics. They acknowledge that generics would be a benefit to the language, and they have acknowledged that generics are by far the most-requested language feature from full-time Go developers. The only thing stopping them from implementing Generics is the inherent (purely technical) difficulty in providing it in a correct, performant, and type-safe manner.

The reason the Go team cannot look to Java, or Rust, or any other languages which provide generics and say "we will implement it exactly as they have" is because Go is as different from Java and Rust as Java is from Rust. Generics had to be individually implemented in each of those languages, and it was a fairly massive undertaking to do so, and there are a lot of folks that say that in Java's case in particular it was implemented poorly but now that it's implemented they're stuck with it.

Like yourself I'm not an expert on generics, either, but everything I've read in regards to generics in Go has lead me to the above conclusion. I trust the Go core developers to implement generics when they have a suitable plan, and I will gladly use them when they are made available, but in the meantime I intend to enjoy all of the great features of the Go language which are available today.


I preface this by saying I really like using go.

> The only thing stopping them from implementing Generics is the inherent (purely technical) difficulty in providing it in a correct, performant, and type-safe manner.

I initially accepted this, and found the "we don't want to build the wrong thing" explanation reasonable. Some years down the road however that's looking a bit threadbare. I've also read enough conversation threads that it's become very clear a couple of the key decision makers are simply resistant to the idea of consulting with the PLT community for a good design.

I'm happy to wait to Go 2.0 for generics, however, if they yet again recycle this "gosh, it's hard, we just don't know how" I will not be satisfied. There are people walking this planet who know how: ask them.


>An open question: has the ship has already sailed on generics in Go?

Doesn't seem so:

https://research.swtch.com/go2017#generics

>That is, is there too much Go code out there written without generics to ever incorporate generics after-the-fact?

You don't HAVE to rewrite all existing code to using generics, although I'm sure it will be tempting :)


Generics weren't added to Java until J2SE 5.0 — which was years and years after 1.0, and Go is still 1.x, so I personally believe that ship is a long way from sailing.


> One of the primary design principles behind Go is that it be designed to incorporate the best available features of other languages

Is that documented somewhere?


I expected I would find it in https://golang.org/doc/faq but I'm not seeing it there, so I have no reliable sources for that statement at this time.

It's something I hear often, though. That Go is intended to be a "modern" language, with the definition of "modern" being that the opportunity that a blank slate provides allows for the application of the best features and learnings of the languages of the past.


> ... with the definition of "modern" being that the opportunity that a blank slate provides allows for the application of the best features and learnings of the languages of the past.

Application of the best features and learnings to a particular problem domain. The (intended) domain is Google-scale code bases that live for decades. The ideas that are important there may not be applicable anywhere else. If they are, it's more by happenstance than design.


Like C, Go is a small language. Given that the creators of go like its smallness and simplicity, all those features are never going to be added to Go.

When Bjarne Stroustrup wanted to add OO features to C, he created C++, initially as a translator that output C. If someone wants to add features to Go, they can create a "Go++" to Go translator, with pattern matching, generics, tagged unions. Clearly it's guaranteed to be very popular! /s


It's the approach Robert Griesemer (member of the Go core team) chose to prototype implementation of operator methods in Go: https://github.com/griesemer/dotGo2016


Actually it looks like he forked and modified the go compiler itself.


> First, functional programming is particularly difficult in Go. In fact the language discourages functional programming.

Well, if I were the king of the forest, I'd move functional programming from Rust to Go. With Rust, there's a lot of this higher level stuff in a supposably lower level language that would be more at home and useful over in the two letter language.


> there's a lot of this higher level stuff in a supposably lower level language

I feel like you're suggesting that "high level stuff" is bad because it's "high level stuff."

In my opinion, the goal of low level languages is to operate under certain constraints. If you can operate under those constraints and still include "high level stuff," then you should.


You seem to be conflating capability and abstraction. Rust has low-level access to hardware and execution but provides a high level of abstraction.


In what way are these tools not also useful in Rust? Why can't we have both?


For Go people: How (learning) Go made you better programmer?

I haven't written any of these two languages but I have read Rust doc few times in depth and I constantly miss many of it's features in my daily .net work since then.

Example: -Optional over null -Union types -Trait implementation is independent from source and target models


Go made me appreciate static typing and a compiler.

Before picking up Go around the 1.0 release, the last time I spent any significant time with those tools was 10 years prior as an undergrad using Java. Java really made me hate those things. I spent the years in between with languages like Ruby, JavaScript, and Python.

Now I actually prefer using compiled, statically typed languages, Rust being the most recent one for me (and I still dislike Java).


Welcome to the dark side =)

I am not a Java fan either but I felt dynamic languages even worst. Since then I have loved to modern static type systems like in Rust (in theory) and Elm/Haskell.


Go is more about pragmatism. If you need to deliver a web API today it is definitely a better choice than Rust and many other languages. Tools such Godoc encourages you to dive into the source code, something that is missing on many languages(i.e. Apple Swift/Objective-C). Shortly said I think it makes you a more pragmatic developer.


I see. Quite a different motivation.


> How (learning) Go made you better programmer?

It didn't. Go offers nothing that a dozen other languages haven't already offered, and fails to include important features that are standard in every other modern language. It is simplistic to a fault.


You know, that is my immediate reaction as well. But if I'm more introspective it did teach (or reinforce) a few lessons that are worth knowing.

Dependencies have a cost (even if they are easy to manage). Abstractions have a cost (even if they are easy to write). Consistency is often better than best case performance. Code style doesn't matter. Scriptable tools are invaluable. Make ain't that bad. Enjoying your team is more important than enjoying your language.

All told, I don't think Go will ever be my first choice, everything else being equal, for anything beyond what I like to call "bash++". But it also won't be a reason I don't take a job, or move to a team and if my team wants to use it, I won't object too strongly.


> How (learning) Go made you better programmer?

It got me to reconsider how I view tooling, linters, etc, and my work is better for it.

As far as the language design itself, I do not believe I learned anything new from it.


It taught me that simplicity and good tooling are more important than purism about types.


This article should be called, "Things I'd like to see in Go from Rust".


Rust is really a language that pulled a lot of concepts that were done elsewhere, into a really solid nice package.

Go is unusual in the new language space in that in eschewed many of these modern techniques. Swift comes to mind as a comparison, which has many of the features that the author misses.

Personally I like the examples offset by a single other language as it's less context switching.


That's the feeling I get when using Rust: all of the bits of the language appear to work well together. People clearly thought about how all of the features in Rust would interoperate; it was designed.

Go, on the other hand, continually feels like a language that wasn't designed as much as it accumulated. None of the parts seem to work in concert. Nil by itself was a bad idea, but when combined with actually-nil-but-not-really interfaces, it leads to subtly broken code. Tuples feel bolted on as second-class citizens, and tuple-based error patterns combined with sometimes-nonsensical zero values for types makes it uncomfortably easy to accidentally use invalid values when you have a typo in error-handling. Implicitly implementing interfaces makes sense until you type-switch on interfaces at runtime, and then through edits elsewhere one interface becomes a distinct subset of the other interface — depending on how they're ordered, you may never hit the other code.

Some of the decisions made in golang make sense in isolation, but in concert they lead to confusion, subtle bugs, and copy-pasted code everywhere.


I feel the exact opposite... Go is a bold design, if not an elegant one, yet powerful. Rust is a design-by-committee language, built from accretion and removal. Its origins as a managed language, pivoted and is now a second system C++ replacement -- the only one, to be fair.


Elegant is.. not the first word I'd use to describe Go. Maybe the core of the language is, but in practice it is anything but, between the error handling, PRY (please repeat yourself), relative inability to create abstractions, and neutered type system.


Go is an opinionated design.

It is very strongly focused on one particular approach of doing things. If you happen to like that approach, you'll find Go smooth and natural. If you don't, you'll find Go annoying and pointless.


> Go is a bold design

What do you find bold about Go's design? (Curious, not looking to start a pointless debate)


Not only Rust but many languages that are moving in the same direction.


Crystal would be a great choice for the author.


Do language​ debaters all think every human should speak one language?...


I think it is more about how efforts in the software community come in finite amount and it fell pointless and damaging to waste so much of it of unsatisfactory language. If i learned of a esteemed professor choosing to publish their latest research in Italian i would be honored, but I would also consider i a terrible idea.


Yes. And it should be Lojban. ~


I'm not sure I understand. Could you please translate your comment into Lojban?


[flagged]


Please don't do programming language flamewars on HN.


There is no one with academic credentials in programming language theory in a position of power with Go. This is a fact.


That obviously doesn't amount to having "no idea about languages".

This is the lamest sort of language spat. It's football hooliganism except not about football. We don't want it here.


> That obviously doesn't amount to having "no idea about languages".

True. But it's a complex topic so in reality these are highly correlated.

> This is the lamest sort of language spat. It's football hooliganism except not about football.

Admittedly my top level comment had little substance to back it up. But as others have pointed out in the thread Go is objectively several decades behind the times. If that doesn't count as not knowing about languages then I don't know what does.


That's just not justifiable. Agree or not with the design decisions behind Go, its creators are at the far opposite end of "no idea about languages."


Then how did they come up with Go? Alternatively, if they are knowledgeable about language design, what other good language designs have they come up with?

I am perpetually baffled by this particular defence of Go. Go has a number of real strengths, but it also has several howling, inexcusable, flaws. How can you possibly say that that this is the work of people who are expert in language design?


Rob Pike and Ken Thompson are the authors of, among many other things: the original Unix, Plan 9, B (the predecessor of C), Inferno (a successor of Plan 9), UTF-8. They definitely are experts in language design.


> the original Unix

Not a language.

> Plan 9

Not a language.

> B (the predecessor of C)

A version of BCPL, stripped down to fit on the hardware they had. Considerably less sophisticated than Algol, which had been designed years before.

> Inferno (a successor of Plan 9)

Not a language.

> UTF-8

Not a language.

> They definitely are experts in language design.

What?


Amen


There are no experts in language design in this field. While you might feel strongly that some things are very wrong, it doesn't mean that "the right way" you have in mind was designed by professionals. Academically-influenced languages are pretty bad at this too.

It's hard to admit, but all of the languages we have are of amateurish quality.


While you might feel strongly that some things are very wrong, it doesn't mean that "the right way" you have in mind was designed by professionals.

Does the "wrong" way always tragically win in the marketplace of ideas? Maybe our (sub)culture has a screwed up idea of what "right" is?


Amateurish in relation to what?


Programmer's idealistic thinking, perhaps?


Why is it that some languages which are lauded for their programming language design aren't used? Alternatively, if "language design" as you think of it was all that truly mattered, why isn't the programming world as you wish it would be?

(Such things were asked in the Smalltalk community for years.)


I think Smalltalk is a bad example for this. I've been told by Smalltalk programmers that everything in that eco system used to be insanely expensive. A better example is probably Haskell or Lisp. As you are probably trying to imply the learning curve seriously matters. Go is a true winner here.


I've been told by Smalltalk programmers that everything in that eco system used to be insanely expensive.

There was a period of time when this was true, which helped to kill Smalltalk mindshare. Then, there was a period of time when there were many economically priced Smalltalk environments, and a even a good FOSS one. Now, we have a couple of good FOSS environments.


Right; so expensive that an entire OOP system with a GUI fit into an image that ran in half a meg of RAM.

Firefox can't render a damned favicon with the resources that Smalltalk used.

Everything you're doing now either was or would have been insanely expensive in 1983.

Emacs used to be derided as being an acronym for "eight megabytes and constantly swapping".

Sure, a big deal on a Sun3 with 4 megs of RAM.


Half a meg of RAM is cheap. A $5000 software license isn't.

It wasn't the price of RAM that made Smalltalk expensive.


Look up Pike's resume. Look up Thompson's. Look at your own. Those guys have far more experience at designing (and even using) languages than you do.

You may not like the choices they made. Fine. But stop assuming that it was from ignorance or incompetence. It wasn't.


Consider that rather than "howling, inexcusable, flaws", people may have different ideas about what's really important in a programming language.


There are opinions, and there are qualifications. We are dubious of the Go team's opinions because of their lack of qualifications.


Well, in fairness at least one of them contributed significantly to the work that generated the design of the language that has powered almost all of computing one way or another for decades (in spite of its many and varied howling and inexcusable flaws, as you'd call them). I'd say that in-practice that beats any aesthetic view of 'design' you have in mind.


This is entirely incorrect. You may not agree with the design decisions, but to state that the creators were ignorant is unjustified.


Wasn't Go Pike & Thompson leading development? I'm not so sure its easy to argue they entirely lack experience with languages..


They had tons of experience with languages work in the 80s, which is probably why Go feels like C with its basic problems fixed.


No, they had tons of experience at Google scale and was a language born out of frustration as much as need. They needed a language that was:

1) comparable with c++ in terms of speed

2) had extremely fast compilation times

3) easy to use, learn and familiar looking, for quick engineer buy in

4) easy to write concurrent & parallel work with

5) designed for tooling & network applications

6) batteries included

Among many, many others. Neither is Go an hammer, nor is everything a nail. For the use cases Go was designed for, I am yet to use a language as pleasant to work with as Go.


1) Any statically typed language nowadays is comparable with C++ in terms of speed, unless you fuck up the implementation really badly.

2) This is a complete non-issue -- with Google infrastructure, it's enough to not be significantly slower than C++, which is really a low bar.

3) Go is definitely easier to use than C++, I agree. That said, it also has enough of idiosyncrasies to make it familiar mostly to people used to writing Plan 9 C, starting from "nil" instead of "null", and ending with "dial" instead of "connect".

4) I never noticed how it is any easier to do it than in, say, Java. Most of the large Go programs I've seen tend to leak goroutines, for one thing.

5) Maybe it was designed for these, though I don't quite see the way it's better suited for network applications than, say, Java.

6) It's also a total non-issue at Google.

I have a year of experience writing Go tooling and network applications at Google, and it definitely wasn't enough for me to see the light. The rest of my team had quite similar experience (except of one guy who was a Go fan already before joining the company), and we would often make fun of Go's inconsistencies, idiosyncrasies, and the whole NIH approach of the language authors and maintainers.

Go is not bad language, it would have been great if it was 1989, and your only serious alternative was writing ANSI C. Unfortunately, it's been almost two decades since the 80s, and we figured out some things in the meantime. We now know how to do generics correctly, for one thing, and we already understood that null pointers have been a billion dollar mistake. The worst sin of Go though is that in the true "worse is better" spirit of Unix, it filled a gap for a better C++ by being only marginally better, taking away space for other, actually better contenders that don't happen have a billion dollar company backing them.


> is that in the true "worse is better" spirit of Unix, it filled a gap for a better C++ by being only marginally better, taking away space for other, actually better contenders that don't happen have a billion dollar company backing them.

I think it ended up being 1) not sufficiently low-level, and 2) a bit too insular in its ecosystem, to really fill that niche. Which is what allowed Rust to seriously contend for it, and I think Rust is going to be the winner.


That's certainly my hope.


> Among many, many others. Neither is Go an hammer, nor is everything a nail. For the use cases Go was designed for, I am yet to use a language as pleasant to work with as Go.

You need to learn more languages (and really learn them).


I feel these assumptions were true when Go design started, but the world has moved on. Even 'boring' languages such as Swift (Apple default) and Java8 has generics and functional programming now.


Even Fortran added some support for generic programming in 2003, and functional programming before that. It's all about how general purpose you plan on being...


Generic procedures were already introduced in Fortran 90, i.e. in 1991.


They weren't true then, but yes they continually become less true.


I can't believe you can look at that ugly colorscheme whole day working in even uglier language which rust really is.


Here we Go


Here we Go

We're rewarding these posts with attention. I guess on some level, these language wars are gratifying.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: