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

Bringing up goland always annoys me for some reason. Like, it's really practical, it is fast, but not actually low-level, it compiles fast, and most importantly it is very popular and has all the libraries. It seems like I should use it. But I just almost irrationally hate the language itself. Everything about it is just so ugly. It's a language invented in 2009 by some C-people who are apparently oblivious to everything that excited PL design folks for the last 20 years (as of 2009). PHP in 2009 was already a more modern and better designed language than goddamn golang. And golang didn't really improve since. I just cannot let it go somehow.



It is worse than that, as Go initially lacked generics (introduced by CLU and ML in 1976), still doesn't do even basic Pascal enumerations (1970) rather the iota/const dance, let alone the 1990's programming language design surface.

I only advocate for it on the scenarios where a garbage collected C is more than enough, regardless of the anti-GC naysayers, e.g. see TamaGo Unikernel.


> Go initially lacked generics

And even though it has them now, the generics syntax is pretty clunky IMO.


> still doesn't do even basic Pascal enumerations

The term you are looking for is sum types (albeit in a gimped form in the case of Pascal). Enumerations refer to the value applied to the type, quite literally, and is identical in Pascal as every other language with enumerations, including Go. There is only so much you can do with what is little more than a counter.


I'm fairly sure he's referring to enumerations actually.

Pascal doesn't require case matching of enumerations to be exhaustive, but this can be turned on as a compiler warning in modern Pascal environments, FreePascal / Lazarus and such.

Go only has enums by convention, hence the "iota dance" referred to. I've argued before that this does qualify as "having enums" but just barely.

It wouldn't have been difficult to do a much better job of it, is the thing.


> Pascal doesn't require case matching of enumerations to be exhaustive

Normally in Pascal you would not match on the enumeration at all, but rather on the sum types.

    type
       Foo = (Bar, Baz)

    case foo:
       Bar: ...  // Matches type Bar
       Baz: ...  // Matches type Baz
The only reason for enumerations in Pascal (and other languages with similar constructs) is because under the hood the computer needs a binary representation to identify the type, and an incrementing number (an enum) is a convenient source for an identifier. In a theoretical world where the machine is magic you could have the sum types without enums, but in this reality...

Thus, yes, in practice it is possible to go around the type system and get the enumerated value out with Ord(foo), but at that point its just an integer and your chance at exhaustive matching is out the window. It is the type system that allows more flexibility in what the compiler can tell you, not the values generated by the enumeration.

> Go only has enums by convention

"Enums by convention" would be manually typing 1, 2, 3, 4, etc. into the code. Indeed, that too is an enumeration, but not as provided by the language. Go actually has enums as a first-class feature of the language[1]. You even say so yourself later on, so this statement is rather curious. I expect you are confusing enums with sum types again.

[1] Arguably Pascal doesn't even have that, only using enums as an implementation detail to support its sum types. Granted, the difference is inconsequential in practice.


Pascal enums are not sum types, because they are not the sum of multiple types. They are an enumeration of discrete values, which is why they're called enums.

Sum types in Pascal are called variant records:

  type
    FooKind = (Foo, Bar, Baz); (* An enum *)

    FooOrBaz = record (* This is the sum type *)
      case foo: FooKind of
        Foo: (quux: Double);
        Bar: (zot, zap: Double);
        Baz: (xyzzy: String);
      end
Rust conflates the 'enum' keyword with sum types. Pascal does not do this. One of us is confused about what a sum type is. It isn't me.

As for Go, my full opinion on that subject may be found here. If you're... curious. Let's say.

https://news.ycombinator.com/item?id=40224485


> This is the sum type

This is the exact same thing, except in addition to the tag there is also a data component. Yes, this is the more traditional representation of sum types, but having an "undefined" data component is still identifiable as a sum type. It is the tag that makes the union a sum type.

In Typescript terms, which I think illustrates this well, it is conceptually the difference between:

   { kind: 0 } | { kind: 1 }
and

   { kind: 0; data: T } | { kind: 1; data: U }
Which is to say that there is no difference with respect to the discussion here.

> They are an enumeration of discrete values

Yes, the "tag" is populated with an enumerator. There is an enumerator involved, that it is certain, but it is outside of the type system as the user sees it. It's just an integer generated to serve as an identifier – an identifier like seen in the above examples – but provided automatically. The additional information you can gain from it, like exhaustive matching, comes at the type level, not the number itself.

> Rust conflates the 'enum' keyword with sum types.

Right, because it too uses an enumerator to generate the tag value. Like Ord(foo) before, you can access the enumerated in Rust with something like

    mem::discriminant(&foo)
The spoken usage of 'enum' in Rust is ultimately misplaced, I agree. An enumerator is not a type! But it is not wrong in identifying that an enumerator is involved. It conflates 'enum' only in the very same way you have here.


There's absolutely a difference between an enumeration and a sum type.


Exactly. One describes a type, the other a numberer. Very different concepts, even if the latter is often used in the implementation of the former (e.g. in Pascal and Rust). Glad to see you are past your earlier confusion.


You do not understand what a sum type is. At all.

There are innumerable ways you can rectify this lack of understanding if you want to.


There may be innumerable (ironic) ways for someone else to explain what it means, but we are here to understand what you mean. The only logical way to achieve that is for you to tell us.

1. If you have a pet sum type definition, let it be known. But traditionally, a sum type is better known as a discriminated or tagged union. So far, this is what we understand Pascal offers: A union type that discriminates its subtypes by an enumerated value.

2. The tag that discriminates the type within the union (or whatever your explanation above ends ups calling it) is, in implementation, generated by a process that assigns a number to each entity; something also true of Rust. This is undeniable, as proven by the use of Ord and mem::discriminant. If you have another name for that numberer, if not an enumerator, let it be known.


So every language have to implement every features released in the last 50 years?


Not necessarly, but designing for stone age computers isn't ideal either, even C, Fortran and COBOL have progressed during those 50 years.


I expect it to implement features that have become ubiquitous in every other mainstream language from the last 30 years, yes.


But then what purpose would it serve? The last 30 years has brought no lack of new languages, not to mention evolution of older languages. Just use one of them.

The purpose of creating yet another language with Go was to break from what everyone else was doing, to see if a "simple" language would stop developers from playing with fun language toys all day to instead focus on actual engineering.

Arguably it was successful in that.


The purpose was to get rid of C++ compile times and replace C++ with Go, failing that, they decided to pivot the story.

https://commandcenter.blogspot.com/2012/06/less-is-exponenti...

They also got lucky with Docker and Kubernetes, pivoting from Python and Java respectively into Go.


Numerous languages already got rid of C++ compile times. That didn't necessitate another one. Certainly Go wouldn't want C++ compile times any more than any other language, but as far as justifying its creation that would not be sufficient justification alone.

Legend has it that Go was conceived while waiting for a C++ program to compile, if that's what you are thinking of?


That's how you end up with C++ and soon C#.


No, the person you were replying to was advocating for the intersection of ubiquitous features. C++ seems to be aiming for the union.


We also end up with C23, Fortran 2023, COBOL 2023, Scheme R7RS,... even those oldies embrace modern ideas.


It’s really not. The strawman that if we add a few features that have stood the test of time in every other language we’ll end up with C++ is just not true. Nobody is proposing adding SFINAE-based conditional compilation, rvalue references, multiple inheritance, or any of the million other Byzantine features that make C++ virtually impossible to use correctly. Adding sum types and a match statement does not necessarily start you down that path.


When we can call it Go++


I know, I'm on the same boat. What I realized is I just need to avoid the companies using Go and I don't really need to be vocal about my dislike. It's not my loss if others find the language useful, but for me it either solves problems I'm not interested in solving, or the language and tooling just does not make it for me.

But, I can always just write Rust and be happy where I am. Or, to be honest, would not be very unhappy with F#, Haskell or Ocaml either.


> I just need to avoid the companies using Go

and they also will avoid you! A monthly go-lang meetup in San Francisco impressed me as the only meetup I have ever been to where no one (in a crowded venue) seemed to want to talk to anyone outside their clique


They don't like hearing that the new exciting feature that the new go has was already in every other programming language 10 years ago.


>What I realized is I just need to avoid the companies using Go

What do you mean, exactly?


I'd imagine not seeking employment at Google is a big part.


Go is definitely used a lot more outside of google as of late.

Anecdotally I would say where a lot of companies would have used Java in the past they are now turning to go for their server-side/backend service implementations.


Also it feels like pretty much everything in the k8s/container/etc. space is go-related, which kind of makes sense.


Why does it make sense? You can implement a container in any language that can make system calls.


I've had to use go occasionally and it feels like the language is designed to stop me from achieving my goals.

The standard library is unimpressive (to be generous), it has plenty of footguns like C but none of its flexibility.

Also for some reason parenthesis AND \n are required. So you get the worse of C and python there.


> The standard library is unimpressive (to be generous)

Coming from Python, this is one of the major things that I just can't get past with golang (despite having to use it for work). The standard library has a lot of really interesting/impressive/useful things to cover niche cases, but is missing a lot of what I would consider basic functionality that I keep running into requiring me to go get an external module to solve the problem.

Then, on top of that, the documentation for external modules is extremely terrible. In many cases the best you can get is API documentation in the form of "these are the functions, this is what they take and return" with no explanation of what those values need to be, what the function does with them, and so on; a simple list of functions. In others, there is that plus example code which doesn't work because it hasn't been updated since the last time backwards-incompatible changes were made so you end up down a rabbit hole of trying to debug someone else's wrong code.

The only thing letting me write effective golang at this point is that VSCode can autocomplete a lot of method calls, API calls, and so on, and then tell me what parameters they need, but even then I'm just guessing about what function might exist and what it might be called.

The language itself is okay and the more I use it the more I understand why they implemented all the stuff I hate (like a lack of proper error handling leading to half of my lines of code being boilerplate `if err != nil` blocks), but if the tooling around it wasn't so good no one would take it remotely seriously.


You're intended to run gofmt on every save. golang is designed to be a sort of straight-jacket that forces everyone to write code in the same way (style etc) so that the junior devs can understand it clearly.


And so that people (of any level) don't bikeshed over silly things like tabs and spaces or { and newlines.

I really like this about go - that it formats code for you, and miss it in other languages where we have linters but not formatters, which is a terrible idea IMO.


What mainstream languages don’t have formatters nowadays? Rust has rustfmt, C and related languages have clang-tidy, python has Black…


I mean built in that everyone uses. There are of course third party formatters.


You can force everyone on a project to use a formatter just as easily in any of those languages as you can in Go, with a few lines in your CI job definitions. Whether they're third-party or not is irrelevant.


It's not irrelevant, it's the entire point. The whole Go ecosystem uses a single formatter. There's no need to force anyone, everyone just uses gofmt. You will not be able to replicate that level of ubiquity easily at all.


Not true. Because after running go fmt and pushing our CI fails because of other stylistic concerns that are checked by another tool.


Not really true because you have both gofmt and gofumpt, and gofmt can be run with -s or not, and also lots of projects are using separate linters to enforce maximum line length.


But true enough.


You can only force everyone on a project to use a formatter if you are the one who has the authority to decree what will be done on the team. OTOH, if you are but a team member and you join a team where the manager does not think common formatting is important, then you get f*ck all.

So being built-in, idiomatic and expected cannot be over-appreciated.


that's your preference but not universal


My only preference is not to have to think about whitespace etc. I guess others who feel differently certainly wouldn't like Go, and that's ok!


Why are you talking about go fmt? I'm talking about parser of the go language

If I write

    if x
    {
    bla
    }
it will not compile, because the { needs to be on the same line as the X (for no reason whatsoever).


I’m convinced there’s a contingent of devs who don’t like/grok abstraction. And it overlaps partially with stated goals of an easy language to onboard inexperienced devs with.

Nothing wrong with that, but it will probably never work for me. Newer versions of Java are much more enjoyable to work with versus Go.


> I’m convinced there’s a contingent of devs who don’t like/grok abstraction.

I am one of those. I grok abstractions just fine (have commercially written idiomatically obtuse Scala and C#, some Haskell for fun, etc.), but I don't enjoy them.

I use them, of course (writing everything in raw asm is unproductive for most tasks), but rather than getting that warm fuzzy feeling most programmers seem to get when they finish writing a fancy clever abstraction and it works on the first try, I get it when I look at a piece of code I've written and realize there is nothing extraneous to take away, that it is efficient and readable in the sense of being explicit and clear, rather than hiding all the complexity away in order to look pretty or maximize more abstract concerns (reusability, DRY, etc.).

This mindset is a very good fit for writing compute-heavy numerical code, GPU stuff and lots of systems level code, not so much for being a cog in a large team on enterprise web backends, so I mostly write numerical code for physics simulations. You can write many other things this way and get very fast and bloatfree websites or anything else, but it doesn't work well in large teams or people using "industry best practices". It also makes me prefer C to Rust.


>I get it when I look at a piece of code I've written and realize there is nothing extraneous to take away,

"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."

- Antoine de Saint-Exupery

https://www.brainyquote.com/quotes/antoine_de_saintexupery_1...


Given how go's binaries are 500x bigger than other binaries, I'd say it has still something to take away :p


> I’m convinced there’s a contingent of devs who don’t like/grok abstraction

I am one of them. I don't like Go, though. Enums and tagged unions aren't abstractions but fundamental features in my book. It's pretty transparent how they look in memory and there's nothing hidden about them.

What does confuse me are things like macros or annotations that magically insert something and make the code incomprehensible. I'm sure it's convenient to use, but it makes my brain try to manually translate it to simple instructions like a foreign language.

In my free time I like using Rust without custom traits (except a few iterators), that's close to the sweet spot for me.


I guess I’m in that camp. I can come up with a good abstraction after working on a problem for a while and refactor it into my code. Or I can come up with a really simple abstraction (eg a Go interface with 2-3 methods), and that usually works well. But I try to avoid starting a project by defining a bunch of abstractions, since I just end up writing loads of boiler plate. Yes, I’m probably doing some things wrong.


Sounds about right. Proper abstractions are difficult to get right up front, might as well pull them out only when they're obvious and profitable.


Strange that you bracket don't like/don't understand together like that.

The vast majority understand abstractions just fine, though each takes time to understand. However most people like their own abstractions best, and those of other people less. To me hell is living in a world of bad abstractions created by someone else.

Every abstraction created adds to cognitive load when reading the code and to the maintenance burden of that code. So you have an abstraction budget, which is usually in overspent IME and needs to be carefully controlled. Most of the most horrible codebases are horrible because they have too many of the wrong sort of abstraction.


Everyone lands at a different spot.

Personally, I don't want to write any new code in something that doesn't have ADTs, or the moral equivalent (Java's sealed classes). I've already written a lifetime of code without them, so I suppose part of that is not wanting to write another 20 years of the same code. :)


If you don’t like subclasses changing code, isn’t inheritance the real problem?


Man, Go gets a lot of hate on here. It's certainly not the most flexible language. If I want flexibility + speed, I tend to choose Nim for my projects. But for practical projects that I want other people to be able to pick up quickly, I usually opt for Go. I'm building a whole product manufacturing rendering system for my company, and the first-class parallelism and concurrency made it super pleasant.

I will say that the error propagation is a pain a lot of the time, but I can appreciate being forced to handle errors everywhere they pop up, explicitly.


So much of language opinion is based on people's progression of languages. My progression (of serious professional usage) looked like this:

Java -> Python -> C++ -> Rust -> Go

I have to say, given this progression going to Rust from C++ was wonderful, and going to Go from Rust was disappointing. I run into serious language issues almost daily. The one I ran into yesterday was that defer's function arguments are evaluated immediately (even if the underlying type is a reference!).

https://go.dev/play/p/zEQ77TIP8Iy

Perhaps with a progression Java -> Go -> Rust moving to rust could feel slow and painful.


I'm curious how one ends up with such ahistorical sequence. I'd expect it to be more aligned with the actual PL history. Mainstream PLs have had a fairly logical progression with each generation solving well understood problems from the previous one. And building on top of the previous generation's abstractions.

Turbo Pascal for education, C as professional lingua franca in mid-90s (manual memory management). C++ was all the rage in late 90s (OOP,STL) . Java got hot around 2003 (GC, canonical concurrency library and memory model). Scala grew in popularity around 2010-2012 (FP for the masses, much less verbosity, mainstream ADTs and pattern matching). Kotlin was cobbled together to have the Scala syntactic sugar without the Haskell-on-the-JVM complexity later.

And then they came up with golang which completely broke with any intellectual tradition and went back to before the Java heyday.

Rust feels like a Scala with pointers so the "C++ => Rust" transition looks analogous to the "Java => Scala" one.


>I'm curious how one ends up with such ahistorical sequence.

they are all actively in-use.. if gp is earlier in their career, it could all be in last 10 years.


I learnt QuickBasic, VisualBasic, Java, C, Python, Go, C++ in that order.

I'd never do a project in go.

Go suitable for networking? Really? With no packed structs and no way to set the endianness?


Go is definitely of the “worse is better” philosophy. You can basically predict what someone will think of Go if you know how they feel about that design philosophy.

I remember that famous rant about how Go’s stdlib file api assumes Unix, and doesn’t handle Windows very well.

If you are against “worse is better” like the author, that’s a show stopping design flaw.

If you are for it, you would slap a windows if statement and add a unit test when your product crosses that bridge.


> Go’s stdlib file api assumes Unix

Until you want to do unix things like mmap() and madvise() of course. In which case it assumes an OS without those really basic features.


The problem is that most of the time, errors are not to be handled but only bubbled up. I've also seen it in Java with checked exceptions: the more explicit error handling is, the more developers feel they should somehow try to do _something_ with the error when the correct thing to do would actually be to fail in the most straightforward manner. The resulting code is often much heavier than necessary because of this and the stacktraces also get polluted by overwrapping.


The problem with the opposite is, since everything gets invisibly bubbled up to the top, you are not able to tell what errors do need to be handled. You only find those out from runtime failures and that's no good if you care about reliability.


You are right, I wouldn't want totally invisible bubbling either. I like Rust's ? notation although it's not perfect and I'm sure another language could do better maybe with more structured error classes.


Sounds like a lack of good code review.


That's just another way of dismissing the problem as a "skill issue" and is not helpful. While the problem can be prevented by having strong coding standards, many teams do not have the luxury of wisdom and thus recreate this exception tar pit again and again.


I use golang for work and have done a fair amount of Rust programming. Rust feels like the higher level language. This really shouldn't be the case.


go’s error handling patterns, while lacking every established feature that makes it ergonomic, is baffling.

Embarrassing that developers are still forgetting nil pointer checks in 2024.


The error handling is one of the worst parts of Go for me. Every call that can fail ends up being followed by 3 lines of error handling even if it's just propagating the error up. The actual logic get drowned out.


I would kill for some kind of `err_yield(err)` construct that handles propagating the error if it's the caller's problem to deal with.

That said, I discovered that Go has the ability to basically encapsulate one error inside of another with a message; for example, if you get an err because your HTTP call returned a 404, you can pass that up and say "Unable to contact login server: <404 error here>". But then the caller takes that error and says "Could not authenticate user: <login error here>", and _their_ caller returns "Could not complete upload: <authentication error here>" and you end up with a four-line string of breadcrumbs that is ostensibly useful but not very readable.

Python's `raise from` produces a much more readable output since it amounts to much more than just a bunch of strings that force you to follow the stack yourself to figure out where the error was.


> I would kill for some kind of `err_yield(err)` construct that handles propagating the error if it's the caller's problem to deal with.

This is called (>>=)[0], but most of the industry is ignorant enough to call it impractical and non-pragmatic (as opposed to their pragmatic `if err`)

[0] https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelu...


Fast to compile, fast to run, simple cross-compilation, a big standard library, good tooling…

As ugly and ad-hoc as the language feels, it’s hard to deny that what a lot of people want is just good built-in tooling.

I was going to say that maybe the initial lack of generics helped keep compile times low for go, but OCaml manages to have good compile times and generics, so maybe that depends on the implementation of generics (would love to hear from someone with a better understanding of this).


There are a million little decisions that affect compile time. A big factor here is inlining. When you inline functions, you may improve the generated code or you may make it worse. It’s hard to predict the result because the improvements may come about because of various other code transformation passes which you perform after inlining. After inlining, the compiler detects that certain code paths are impossible, certain calls can be devirtualized, etc., and this can enable more inlining.

Rust is designed with the philosophy of zero-cost abstractions. (I don’t like the name, because the cost is never zero, but it is what it is.) The abstractions usually involve a lot of function calls and you need a compiler with aggressive inlining in order to get reasonable performance out of Rust. Usage of generics still results in the same non-virtual calls which can be inlined. But the compiler then has to do a lot of work to evaluate inlining for every instantiation of every generic.

Go is designed with the philosophy of simple abstractions, which may come with a cost. Generics are implemented in a way that means you are still doing a lot of dynamic dispatch. If you need speed in Go, you should be writing the monomorphic code yourself. Generics don’t get instantiated for every single type you use them with. They only get instantiated for every “shape” of type.


> Rust is designed with the philosophy of zero-cost abstractions. (I don’t like the name, because the cost is never zero, but it is what it is.)

So when the generated asm is the same between the abstraction and the non-abstraction version, wheres the cost?


The point is that different people have different understandings of "cost." You're correct that that kind of cost is what "zero cost abstractions" means, but there are other costs, like "how long did it take to write the code," that people think about.


Cognitive cost is the most important cost to minimize.

A Rust project's cognitive cost budget comes out of what's left over after the language is done spending. This is true of any language, but many language designers do not discount cognitive costs to zero, which, with the "zero cost abstraction" slogan, Rust explicitly does.


> So when the generated asm is the same between the abstraction and the non-abstraction version, wheres the cost?

The generated asm isn’t the same.

There’s also a presupposition here that you know what the non-abstracted version would look like. If you don’t know what the non-abstracted version looks like, you can’t do a comparison.


> I was going to say that maybe the initial lack of generics helped keep compile times low for go, but OCaml manages to have good compile times and generics, so maybe that depends on the implementation of generics (would love to hear from someone with a better understanding of this).

OCaml types are complex enough that monomorphization like Rust or C++ is impossible, so everything is boxed.


> a big standard library

Not really, no. It doesn't even contain wrappers for the most common system calls.


golang feels like someone wanted to write a "web focused" version of C, but decided to ignore every issue and complaint about C raised in the past 25 years

It's a very simple and straightforward language, which I think is why people like it, but it's just a pain to use. It feels like it fights any attempt at using it to do things optimally or quickly.


> which I think is why people like it

Do people actually care that much about languages? I mean, we're here writing English, which is a complete dumpster fire. Go is undeniable perfection compared to the horror that is English. Clearly you and I don't care that much about languages.

I expect people like Go because of its tooling (what also saves English), which was a million miles ahead of the pack when it first came out. Granted, everyone else took notice, so the gap has started to narrow.

> It feels like it fights any attempt at using it to do things optimally or quickly.

Serious question: Is that because you are trying to write code in another language with Go syntax? Go unquestionably requires a unique mental model that doesn't transfer from other languages; even those that appear similar on the surface. Because of that, I posit that it is a really hard language to learn. It is easy to get something working, but I mean truly learn it.

While every programming language requires its own mental model, Go seems to take it to another level (before reaching a completely different paradigm). I expect that is because its lack of features prevents you from papering over "misuse" like is possible in other, more featureful languages, so you feel it right away instead of gradually being able build the right mental model.


The purpose of human language is communication of concepts between two individual thinking people. The purpose of a programming language is literal instruction for a machine.

These are not directly comparable just because we use the same term to describe them.

To your second point, I wholeheartedly disagree. Go is not a difficult language to learn, nor is it particularly unique compared to the type of language it attempts to emulate. In fact I think it’s one of the easiest languages to learn if you already have experience in C-likes because of how obvious it is what it’s trying to do.

I think it is just a bad language. It’s simple to figure out how you need to use it, but it is obnoxious and tedious to do it in that way.


> The purpose of a programming language is literal instruction for a machine.

Toggle switches are for giving instructions to a machine. Programming languages are a higher level abstraction over the toggle switches so that the intent of the toggling can be communicated with other people. You don't just write code, run it through the machine, and then throw it away. Other people, and probably even yourself, will read what was written again and again and again. The language is very much for people first and foremost, with the side effect of also being understandable by machine.

> I think it is just a bad language.

It is – nobody is suggesting otherwise – but you didn't answer the question. Are you writing Go with Go syntax, or another language with Go syntax? Perhaps the best way to answer, if it is that you just didn't know how, is to post some sample code that you find to be obnoxious and tedious and we can see if it is that way because of Go, or if it is because you are trying to use patterns from other languages that don't fit the language.


In all your comments you seem to be hitting the nail on the head.

Someone can say the German language is a bad language. But it is not the language that is bad, it is the person's perception.

When they try to evaluate German while thinking in English it is no surprise they consider it sub-standard. Germans, OTOH, are much better equipped to evaluate the German language than those who only know how to think in English.

(Full disclosure; my grandfather was German but I only know how to think in English.)


Writing questions and suggesting someone else’s answer for them from an imagined situation is not useful or pleasant discussion. Please refrain from doing that.


You are welcome to answer it any way you see fit, but relaying a real world experience in code where you found those aforementioned attributes to be pressing would be a concise way to answer it. I suggested that to help, as you were clearly struggling to broach the subject previously. Certainly don't hold back if you can do better.

There would be no logical reason to make up some imagined situation. I am not understanding your reason for mentioning it. What is the thought process behind your thinking there to help me better understand your intent?

Or, if this is just your subtle way of saying that you've never actually written any Go code in your life and are just making this up because you read someone like it elsewhere, then fine. So be it. But that would well and truly not be useful. Given that you are seemingly here in good faith we can be sure that is not what is going on here and look forward to your reasoned response.


I asked you not to write questions with suggested answers based on your imagination and your response was to just do that again.

I don’t know what your goal is here, but it’s clearly not anything that involves a conversation.


Thank god I'm not the only one. I can still remember when the Go zealots were everywhere (it's cooled down now). Every feature Go didn't have was "too complicated and useless", while the few features it did have were "essential and perfect".

I've really tried giving Go a go, but it's truly the only language I find physically revolting. For a language that's supposed to be easy to learn, it made sooooo many weird decisions, seemingly just to be quirky. Every single other C-ish language declares types either as "String thing" or "thing: String". For no sane reason at all, Go went with "thing String". etc. etc.

I GENUINELY believe that 80% of Gos success has nothing to do with the language itself, and everything to do with it being bankrolled and used by a huge company like Google.


I believe most successes of languages happen because of corporate backing and tooling/library ecosystem rather than language. It's not like most people are using Java because they are in love with the language features.

Personally I also think that if you removed memory safety overnight from Rust, people will still use it. Rust is appealing not because it's memory safe. For some uses it is, but most people flock to Rust because it offers an alternative to C++ without fifty years of accumulated cruft. Rust is a modern language, with a well working package manager/build tool and a wide ecosystem of libraries for every usecase. Memory safety and other features are just a cherry on the top. If Rust used garbage collection I am sure it would also be very popular just because of those other things.

Other languages like D or Nim tried to fit into that space also, but they don't have the budget to really make it. Most of work on those languages is done by unpaid volunteers, so there's little direction and there's a lot of one man projects.


I recommend giving it a second chance. You will at least realize that the "thing string" problem isn't a problem, it's just something you find aesthetically displeasing.

One thing I've learned over the years is that if you go with the grain — not against it — of a language (or any system, really), the design tends to become apparent quicker. "When in Rome," and so forth. Cultural displeasure tends to disappear if you give the native way an earnest chance rather than resisting it. For example, in the beginning, marking identifiers as public by giving them a capital letter struck me as the ugliest thing ever. I don't mind it now. It's never going to be something I love looking at, but it does have the benefit of making declarations' visibility extremely obvious.

I don't think Go's popularity is due to Google at all. Google the company has never really promoted Go (unlike Microsoft with C# and Sun with Java, for example). Go is still treated as a bastard stepchild in many Google projects such as Protobuf/gRPC, Beam, and Google Cloud. The Go team has never seemed very enthusiastic about PR, either. There was that one big redesign of the Go site, but relatively little after that.

I think Go grew by word of mouth more than anything. Projects like Kubernetes, Prometheus, Traefik, etc. helped a lot. Don't forget that it took years for Go to become popular. It wasn't taken very seriously by many in the beginning. Go was not popular within Google until relatively recently. For many years the only serious thing written in Go internally at Google, as I understand it, was the dl.google.com backend.


You're the zealot he was complaining about.


It's funny the single example you provide to back up your point is plainly wrong. The syntax Go went with is obviously better and every modern language uses it too, Rust, Zig, you name it.


Rust at least doesn’t.

  let x: usize = 42;


I now realize I had misread and the parent poster did explicitly say that "thing: String" is fine but "thing String" is not. An odd hill to die on.


As a counterpoint, Go is currently the only language I do not find revolting.

And complaining about "thing string" vs. "string thing" seems high on pedantry.

Yes, there are aspects of Go I really dislike, but I find fewer things to dislike in Go compared to things I dislike in all the other languages I have programmed in.


Whatever reasons are there for using or not the language, tokenising and parsing are absolutely not a problem you want to solve with it.


> It's a language invented in 2009 by some C-people who are apparently oblivious to everything that excited PL design folks for the last 20 years (as of 2009).

Is there a term equivalent to "armchair quarterback" in programming? Most programmers are already in armchairs.

It's the equivalent of yelling at the TV that the ultra-successful mega-athlete sucks. I can't imagine the thought process that goes into thinking Ken Thompson, Rob Pike and Robert Griesemers are complete idiots that have no clue of what they were doing.


No one said they are complete idiots.

They made a deliberate decision to design a language that did not take many developments in PL design since the 70's into account.

They had their reasons, which make sense in the context of their employer and their backgrounds.

Many people, myself included, prefer to program with languages that do not focus so much on simplicity


It was not deliberate, it was ignorance. Time and again, the Go team made comments in various forums for years showing they really knew nothing about programming language development past 2000.

All they knew was C and that they wanted to create a language that compiles faster than C++. That's all.


You're talking about Ken Thompson, Rob Pike and Robert Griesemers, among others.

You're not doing yourself any favors.


They're great examples that just because you're good in one field doesn't mean you're good in other fields. Or even open minded.


> But I just almost irrationally hate the language itself.

That's the point. It's a rejection of the keyboard jockeys who become more concerned with the code itself than the problem being solved.


Golang was created specifically so that Google could mitigate the downsides from lower their hiring standards. It doesn't have any higher design aspirations.

"The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." - Rob Pike

I suppose in a sense this is rejecting the "keyboard jockeys", but probably not in the way you mean.

You cannot separate the tool used to solve a problem from the problem itself. The choice of tool is a critical and central consideration.


I think you're giving far too much weight to that off the cuff quote from one of the creators of Go.

Really I think it's more useful to view it as a better C in the less is more tradition, compared to say C++ and Java, which at the time were pretty horrible. That's my understanding of its origin. It makes sense in that context; it doesn't have pretensions to be a super advanced state of the art language, but more of a workhorse, which as Pike pointed out here could be useful for onboarding junior programmers.

Certain things about it I think have proven really quite useful and I wish other languages would adopt them:

* It's easy to read precisely because the base language is so boring * Programs almost never break on upgrade - this is wonderful * Fewer dependencies, not more * Formatters for code

Lots of little things (struct tags for example) I'm not so keen on but I think it's pretty successful in meeting its rather modest goals.


> Really I think it's more useful to view it as a better C

But Go is nothing at all like C, and it's completely unsuitable for most of the situations where C is used. I'm having trouble even imagining what you're getting at with this comparison. The largest areas of overlap I can think of are "vaguely similar syntax style" and "equally bad and outdated type system". Pretty much everything else of substance is different. Go is GC'd, Go has a runtime, etc.


Clearly you see it differently from people who use go, have a nice day.


No, the vast majority of people who use go are using it in situations where Java or Python would have been appropriate, not C.


To say a better C means it is clearly influenced by C, not that it was intended to replace C in all contexts, but that it's a compiled language in the C tradition which extends C idioms/syntax, adds a good standard library, better strings etc without losing the simplicity which made C attractive.

Just as C++ intended to improve C but went in a very different direction and added a lot more. Crucially, it doesn't add inheritance as C++/Java did, which I think is an interesting choice which I find quite pleasing and avoids a lot of horrible architectural decisions and vast inheritance trees.

There are certainly lots of bits I would change having used it a while, but I find it quite useful to work in and far more like C than say Java, Ruby or Python which it has supplanted more than usage of actual C. Not sure one of the goals was to supplant C usage and that was not at all what I meant to imply.


> To say a better C means it is clearly influenced by C

Influenced by the same person who influenced C, at least, but it is nearly a straight up clone of Newsqueak, with a dash of Oberon, combined with a will to be more Zen than Python.

If you follow the bouncing ball of influence through Newsqueak, Limbo, et al. I'm sure you make it to C. But then why stop there? What about B, BCPL, etc.?


> people who use go are using it in situations where [...] Python would have been appropriate

I'm not so sure about that. Python is a DSL for connecting C functions together. Whereas the biggest criticism of Go (gc, at least, but fair to say it has become synonymous with Go) is around its poor C-interop.

In fact, because of that limitation, Go has developed a bit of a "rewrite those C functions in Go" attitude. While that doesn't indicate that Go is a better C (that's subjective anyway), it does indicate that they are found on the same playground. You're probably not going to rewrite Linux in Go, which might be what you are grasping at, but that's not where C ends. Not even close.

You may have a point about Java. Griesemer was a founding member, after all.


I mean, if you have a coherent explanation for why you made that comparison, it should be pretty easy to communicate...

Your response as it stands is not doing much to fight the "Go enthusiasts are Blub Paradox victims" perception


That's saying the same thing. If you give someone the ability to understand a brilliant language, they will turn their attention to the language and away from the problem. That's just human nature. Shiny attracts us. Let's be honest, we all have way more fun diving deep into crafting the perfect type in Haskell. But Pike indicates that if you constrain developers to bounds that they already know, where they can't turn their attention to learning about what is brilliant, then they won't be compelled away from what actually matters – the engineering.


> then they won't be compelled away from what actually matters – the engineering.

Maybe it is, to the extend that playing with lego blocks authorised by the lego corporation is considered engineering. That, of course, is a silly line to draw for defining the discipline.

> we all have way more fun diving deep into crafting the perfect type in Haskell

What Haskell allows you to do in practice is defining required and missing control flows (for solving your problems) as types[0], and constraining those types with rules that define your business domains the control flows must operate in. That is the actual engineering, as opposed to joining plastic bricks.

[0] https://hackage.haskell.org/package/foldl-1.4.17/docs/Contro...


> What Haskell allows you to do in practice is defining required and missing control flows

It allows that in theory, at least, certainly. That's the whole reason for its existence. But in practice, developers become enamoured with the language and start to forget about the problem. If that weren't a problem we'd all be using Haskell, but back in the real world.


The reason we’re not all using Haskell is because like any language it has pros and cons and isn’t the best choice for every niche. Not because “developers become enamored with the language and start to forget about the problem”.

Anyway, why do Go fans always reach for the Haskell strawman in discussions like this? Most mainstream languages are not nearly as exotic as Haskell, while also not being intentionally crippled like Go. But for some reason Go fans always want to compare it to Haskell.

Even JavaScript, Python and Java are not allergic to adding modern features like iterator map/filter/etc., do you think those are esoteric ivory tower languages too?


> The reason we’re not all using Haskell is because like any language it has pros and cons and isn’t the best choice for every niche.

Exactly. Thanks for reiterating.

> Anyway, why do Go fans always reach for the Haskell strawman in discussions like this?

What's a Go fan? Someone who thinks that Go blows? That is as bizarre as becoming enamoured by a language. What leads one to have feelings about a language anyway? It is an impossible to understand concept for me.

> Even JavaScript, Python and Java are not allergic to adding modern features like iterator map/filter/etc.

In what world are patterns from the 1960s "modern"? Do you consider selt belts in cars to also be a modern feature?


> What leads one to have feelings about a language anyway?

Not a single person reading this thread believes that you are a coolly detached rational observer

Responding to an argument by not only pretending not to have an opinion, but pretending not to understand the concept of having an opinion, is a very interesting rhetorical strategy. Not sure it works


> Not a single person reading this thread believes that you are a coolly detached rational observer

All one of them?

> Responding to an argument by not only pretending not to have an opinion

The "argument" has only ever been about sharing of that which we understand as fact. One can present a case for why an apparent fact is not factual – mistakes and misinformation can, indeed, slip in – but what is fact would not rest on one's feelings towards it. The story of Go is the same whether you love it, hate it, ascribe no emotion towards it, or even if you have never heard of it before.

> but pretending not to understand the concept of having an opinion

Feeling and opinion traditionally do not imply the exact same thing – they are different words for a reason – so it is not clear if you misspoke, don't recognize a difference, or if you are trying to change the subject, but I will, for the sake of quality, assume the former. While I can understand feelings in some contexts, like feelings towards people, I have no idea why an inanimate programming language would conjure feelings? That is like developing feelings towards a grain of sand you found on the beach, which I don't understand either.

I am not about to claim nobody develops feelings for inanimate programming languages. Humans are varieitied and can do all sorts of weird and wonderful things, but that does not imply I understand it. Feel free to explain it, though. That's the beauty of not understanding something: You get to learn!

I mean, that's why I also asked last time. Surely you're not one of those anti-education types?

> Not sure it works

Okay, cool. Is this some kind of problem, or why are you mentioning it?


Is there any evidence that the Go style of constraints increases productivity or code quality or other metrics compared to "shiny" languages? I've heard that point repeated many times, but people have done a decent amount of engineering in many other languages too, without the need to be limited like that.


I expect nobody outside of Google has ever truly taken the time to study it. When was the last time you saw a programmer actually research the effectiveness of their tools and not just land on "I like this. It feels right." I never have!

But I'm not sure it matters. Go was created to test the theory, not because a theory was proven. It didn't have to be successful. It may be that the studies didn't happen even within Google, although that is our greatest chance. We do know Google actually cares about data, unlike programmers.

That said, since Go was released it seems every other language has tried to copy it with their own twist, so while that may not come from a place of evidence, it would appear that the feeling of increased productivity[1] was felt.

[1] Or something adjacent. Focusing on engineering isn't necessarily about productivity. You can't discount productivity, but it is not the top engineering concern, especially in a place like Google.


> since Go was released it seems every other language has tried to copy it

What are you referring to here? I would consider myself quite well-apprised of recent developments in PL theory (and practice) and I am struggling to come up with examples matching this description.

Go's main selling point, at least as of 10 years ago, was its green threading system, and even at the time it was substantially inferior to the green threading systems available in BEAM (Erlang, Elixir) or GHC Haskell


- Java's latest addition of green threads is 100% lifted from Go.

- Rust and Zig's built-in language tooling, including dependency management and an opinionated autoformatter.

- Java's ZGC was an obvious response to Go's GC. There's also the realization that the fewer GC knobs there are to tune the better.

- Possibly Java's quest to add value types as well, not 100% sure on the timeline.

- Broad industry trend towards providing easy cross compilation into static binaries.


> Java's latest addition of green threads is 100% lifted from Go.

Why do you say it was lifted from Go and not from one of the places Go lifted it from, like the two I mentioned?

> Rust and Zig's built-in language tooling

Maybe my memory is failing here, but I don't recall rust ecosystem tooling ever lagging behind Go's. The opposite, if anything.

> Java's ZGC/value types

Can't comment on this one, could be right, although are any of these things clearly sourced from Go? Not disagreeing, I just don't know the history here.

I'm willing to believe that Java is copying from Go, because it's one of the most lumbering languages in popular use today.

> Broad industry trend towards providing easy cross compilation into static binaries.

I'm pretty sure Go does't get credit for this one either. This has been happening independently across many ecosystems as a natural response to increasing containerization and falling storage costs.


> Java's latest addition of green threads is 100% lifted from Go.

or gevent, or many other greenlet implementations across languages, 100%


Deno 2.0 explicitly copied Go in many features, especially with dependencies being referenced via URL, and many of the CLI's commands are inspired by Go such as install, fmt, and test.


> If you give someone the ability to understand a brilliant language, they will turn their attention to the language and away from the problem. That's just human nature.

Not sure which languages you define as brilliant but I’ve never seen this pattern anywhere in my career, in any language. Including Rust, which is often offered by Go fans as an example of an esoteric exotic language.

In everywhere I’ve seen, people are focused on solving some engineering problem, not on showing off their brilliance by solving language puzzles.

This defense of Go is REALLY common but as far as I can tell is purely based on myth.


> I’ve never seen this pattern anywhere in my career

Me neither, but I've never actually tired to look. In honesty, have you? It is not exactly to the faint of heart to study. I suspect only Google is willing to go to the necessary depts. But, if you know of something otherwise, I'm sure we're all interested in the details.

> This defense of Go is REALLY common but as far as I can tell is purely based on myth.

1. Defence? Are you in some kind of fight...? That doesn't make any sense.

2. Myth? Are you confusing the hypothesis on which Go was built with results of experimentation? It very well may be that the hypothesis didn't stand up to experimentation, but what does that have to with our discussion? Furthermore, if you really want to change the subject to talk about that, why have you failed to tell us anything about the details of experimentation?


I recognized exactly that way back in 1995. I used to teach Clipper in the late 80s and early 90s and you could do so much with it. It's competitor was FoxPro, which was far less capable.

However, in hindsight after I quit using it I realized that Clipper developers often focused on perfecting code — myself included — whereas FoxPro developers just got shit done for the client/end-user. #fwiw


Things are what they are, not what someone (yes, even their creator) says they are.

Unless you take a good look at the language itself, you will remain ignorant.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

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

Search: