It is an order of magnitude faster than Python. So it is well suited for performance in many cases.
It is a lot easier to pick up than C/C++. So it is well suited for smaller programs.
I can see Go as a very good middle-ground.
I would say, "it is a lot easier to pick up than C++" as the language specification is much smaller. I wouldn't be so sure about the comparison to C, though.
And please don't get me started on writing concurrent code in C.
That's why corporations like Google invent "middle-ground" languages.
Go from Google
Java from Oracle
C# from Microsoft
These companies need some performance, but they can't hire enough C/C++/Rust devs (not enough exist). They're flush with JS/Python devs, but those languages are too slow.
So they invent these abominable "middle-level" languages, with their insane bloat.
For myself, I'm not interested in mediocrity to serve corporate interests, so I don't touch them. :p Extremes only: Python and C; Ruby and Rust; JS and C++.
Oracle acquired Java with Sun Microsystems, it was originally designed for embedded systems and the dream of “write once, run everywhere”.
The idea of a “hardware JVM” always fascinated me, I seem to recall some parallax microcontrollers that could run a subset of jvm bytecode back in the 90s, but never actually got to play with them.
Go excels in that it is so simple. As the saying goes, you mostly read code, not write it. Go is very easy to understand and review. Which is what you do mostly when working on complex systems in teams. It's extremely easy (and fast) to build and deploy unlike the languages above. That's why companies use go. Not for personal projects, not for drivers, and also probably not for corporate monoliths that require a suit and a tie to contribute.
You will never have an issue with missing dependencies or outdated runtime.
The bigger problem is the weak and inexpressive type system, which is no better for C or Python.
What "stuff" is that exactly? Because Go is designed primarily for backend services and microservices. Considering how much backend software is powered by Python, Java, or *retching sounds* PHP, I highly doubt that is a major consideration in that area.
And even when performance actually does matter to an extend where it becomes a more pressing issue than network latency, Go code performs incredibly well and is more than a match for most requirements.
> No OO
How do you figure? I can write in a completely object oriented style in Go. Also, OO is not a prerequisite for large complex systems, and quite often strict adherence to it can make code much harder to maintain than it needs to be. Maintaining large complex systems requires, first and foremost, code that is easy to grok and maintain. And regarding that particular area, Go runs circles around any major contemporary language, including Python.
> It seems that its popularity exceeds its scope
Considering how widespread it is by now, I highly doubt that.
Not all GC based languages are made alike.
In this regard, Go is far inferior as a systems programming language.
Anyway, Python is not a good comparison, as performance is not one of its main qualities.
I think they're a strong contender... it's somehow simpler than Rust
then again the correctness guarantee may be weaker??
True. But it's a pretty small space to be in. And there are good reasons for that:
a) The only correctness Rust can, mostly, guarantee, is that there won't be unexpected data races or memory bugs. While this is proudly announced often and loudly, it also isn't the most common problem in code...logic bugs...against which the rust compiler can do as little as any other language.
b) Rust can only give these guarantees because it is ALOT more complex than C. That means harder to read, harder to write, harder to learn. And developer time matters. Alot. If I can already ship features, while my competition is still stuck in onboarding, it won't matter if my code has the odd memory bugs...those can be fixed...I will already have the market to myself.
A powerful type system helps quite a lot with logic bugs actually.
A static type system does, and all the languages that Rust has to compete with in its space, have one.
Please, do explain: what does "much less expressive" mean, in technical terms? What specific data modeling can I not do in Go, and what specific bugs can be caused by that?
> and it has null pointers
Yes, so? De-Referencing a null pointer in Go crashes the program, making the bug very obvious. Go made the choice to have null pointers (which do exist in silica), and avoid the complexity of languages who pretend that null pointers don't exist.
It's a tradeoff, and a very good one at that.
You're getting into the Turing tar-pit. There's nothing you can do in Rust you can't also do in Go, technically. Hell, you can do it all in Brainfuck too, if you so desire.
The big thing, though, is ADTs. Being able to say "the value is one of 3 possible values" is a lot easier than saying "here are three values, you should use the non-zero one".
I am fully aware of that. My question is, what specific technical problems are caused by Go not having {feature_goes_here}.
> The big thing, though, is ADTs
Except it isn't a big thing, because for the few use cases where an ADT is actually, really, really, REALLY required, they can be expressed in Go using existing language features.
https://go.dev/doc/faq#variant_types
https://eli.thegreenplace.net/2018/go-and-algebraic-data-typ...
Quote: "It seems that Go can do just fine without adding variant types, due to the challenges mentioned in the beginning of the post and the ease with which the major use-cases can be implemented using existing language features." End Quote
On the one hand, yes, this is more verbose. On the other hand, these use cases are simply not frequent enough to justify making the languages syntax and type system more complex.
Again: Yes, Go lacks many features of other languages. That is on purpose. The language is made to be simple, as in "easy to learn, easy to read, easy to refactor, easy to generate, easy to maintain large bodies of code".
Also, it's not about ADT's being required. They're preferred, and Go's type system suffers for their lack. Go is a living, breathing example of the blub paradox in action.
And I ask again what that is supposed to mean in technical terms, and what specific problems would be prevented if Go's type system was "more expressive".
> They're preferred
I am fully aware that for every given language feature, there are people who prefer that feature. And many languages reacted to that by including everything and the kitchen sink. That made many languages very "expressive", but that expressiveness comes at a cost: It also made the languages themselves become bigger and more complex.
Go isn't about having as many features as possible though. Quite the opposite, it's about having as many features as necessary, and as few as possible. Why? Because it keeps the language small and easy to learn and the code easy to read and maintain.
And to me (and judging by the sucess of Go I am not alone in this), that is a lot more important than a bit more "expressiveness" in things that one may come across every now and then.
Correct. And that isn't a disdvantage.
The fact that Go's type system "cannot handle that" directly in it's type system (functionally, the language itself can handle that easily enough, as shown by the article I linked above) is a choice, which results in a simpler language.
And I still haven't seen any specific problems that would be prevented if Go included this feature directly in the type system. I have, however, seen a lot of extra syntax that Go doesn't need to support in its compiler, Go students don't have to learn, and Go devs don't have to worry about.
I keep telling you the specific problem that would be prevented. You can't forget to handle an enum variant. That is a specific problem that is prevented in Rust, but not Go. And no, the language doesn't "handle that easily enough".
Update an enum in Rust with a new variant? Your code won't compile until you've updated everywhere that matches against it. Do something similar using the technique you linked in Go? Good luck, hope you don't introduce any bugs by forgetting to handle it somewhere.
Yes, the language handles it easily enough. ADTs, despite being the single most used example of "what Go doesn't have" since the language got generics, are not very common outside of the ML-derived-language world.
If they occur at all, they are usually used in a few very specific places. An example are AST types that are used in exactly the part of the parser handling that type.
I expect much like generics, we'll get some new version of Go eventually that half-asses ADTs, with much fanfare celebrating how they were totally always going to do it, they just needed to perfect it.
No, more languages are incorporating them, because most languages operate under the assumption that "more-is-better" is a good design maxime, also known as the "everything-and-the-kitchen-sink" method.
Resulting in exactly the opposite of what Go is, with extreme success, doing.
Fun fact: That methodology in other langages is what made Go's success possible in the first place.
> I expect much like generics, we'll get some new version of Go eventually
I expect the exact opposite, precisely because of generics. Because it has been some time now since they were implemented, and lo and behold: They are rarely used in most codebases, because as it turns out, the people saying "Outside of some collection-types, generics are almost never required" were right in the first place.
This is a good illustration of how to model data using Rust's type system in a way that gives you compile-time guarantees of correct behavior:
https://docs.rust-embedded.org/book/static-guarantees/state-...
> Because we are enforcing our design constraints entirely at compile time, this incurs no runtime cost. It is impossible to set an output mode when you have a pin in an input mode. Instead, you must walk through the states by converting it to an output pin, and then setting the output mode. Because of this, there is no runtime penalty due to checking the current state before executing a function.
> Also, because these states are enforced by the type system, there is no longer room for errors by consumers of this interface. If they try to perform an illegal state transition, the code will not compile!
> Yes, so? De-Referencing a null pointer in Go crashes the program, making the bug very obvious.
At runtime. i.e. production. You think that is just as good as solving the problem at compile time? I certainly don't.
At runtime, i.e. initial testing, pre-commit-checks, integration-testing, QA and then production, yes.
So there are a lot of checkpoints where the system can crash before it ever goes live.
> You think that is just as good as solving the problem at compile time?
No, I don't, and I never wrote that I do.
I do think that it's a lot better than not crashing and running inti undefined behavior when dereferencing a null pointer, which is a problem in older languages, and a source of hard to track bugs.
The problem is: solving it at compile time isn't zero-cost.
Languages that pretend that void pointers don't exist are usually more complex than languages that accept their existence as a fact of the underlying hardware. That extra complexity comes at a tangible cost in development time and maintainability. A language that fails early, and with a clear signal, will sometimes crash in testing, and maybe maybe maybe in production here and there, and such crashes may incur a cost. A more complex language will always incur a higher cost in developer time.
Sure the language in its totality is more complex. At least compared to Go or C. But nothing is forcing you to use every feature of it.
And yet, Go is a huge success in the industry, and one of the main reasons often given for chosing Go over a competing language, is how easy it is to get things started, how easy it makes the onboarding process, and how accessible and maintainable the code is.
> the type checking seriously helps you out when you are changing existing code
If you have Algebraic Datatypes in your codebase, which is not a given. Having a simple, easy to read language helps me out ALL THE TIME.
> But nothing is forcing you to use every feature of it.
And nothing forces C developers to use so many macros that their libraries resemble a completely different language where everything I thought I learned about C flies out the window. Nothing forces Python devs to use nested dictionary-comprehensions, that are, ironically, completely incomprehensible. Nothing forces C++ developers to use generics everywhere, regardless of whether they are actually needed or not.
And yet, that is, unfortunately, what is often happening in the wild.
The point here is; If a language offers X, then X will be used. And it will be used in smart ways, it will be used in unnecessary ways, and it will be used in not-so-smart ways. It will be used when it makes sense, and when it absolutely doesn't.
The thing the developers of Go figured out, and which, in hindsight, is surprisingly obvious, is that there is exactly one, and only one, foolproof way to prevent that from happening: By not having X in the language.
This is a discussion about whether Go "misses" things, or "lacks" things, or if it's designed to not have these things, and if there is a reason why that is.
I have demonstrated, and provided arguments, for why the latter is the case. Aka. the exact opposite of "polemic".
Success of a technology is more often than not dependent on who is behind it. Anything by google will likely see a lot of uptake.
Every language has a story. Some of it is bull some not. Best to try and be objective and not drink every drop of the koolaid.
Disagree.
A Rust program is by default going to be CPU and memory efficient. It is not likely to negatively surprise you in production with weird bottlenecks and unexpected behavior.
The time invested in producing a solution which is statically typed, pays of in spades when it is time to refactor or change something (which is pretty damn often if it is your product). Refactoring a Python/Erlang/Elixir/C/PHP solution is a major PITA and fraught with new bugs.
The time spent optimizing solutions in high level languages when they are falling on their face in production is generally ignored and extremely common. You do not have to be github to face performance problems in Ruby.
$ time http --version
3.2.2
real 0m0.113s
user 0m0.087s
sys 0m0.020s
$ time xh --version
xh 0.18.0
-native-tls +rustls
real 0m0.007s
user 0m0.002s
sys 0m0.002s
[0] https://httpie.io/blog/httpie-3.0.0#speed-upsNot for me. Printing HTTPie's version takes longer than to finish a real http request with xh. I suspect it's because I'm testing it on a relatively old server where the differences are even more pronounced.
[link redacted]
I'm using HTTPie 3.2.1 because Arch doesn't have the latest version available but based on the release notes that shouldn't make a difference.
At that time, this new Python language was a curiosity. It was nice that you could easily replace dozens of C code with one line of Python but everybody was aware it's too slow. However, this window shifted with time. The perceptions of "fast" and "slow" changed for various reasons such as network delays so Python became acceptable in many areas it would be dismissed otherwise. To the point it became the no. 1 language now.
But we are not in the 2000s anymore. We do have powerful, batteries-included languages that are faster than Python. So I expect with time, large parts will be rewritten. However, the area related to scientific computing will stay with Python, just like Fortran programs continue to be used today.
* Easier/safer than C
* Less dangerous than Javascript (statically typed and a good standard library)
* Much faster than Python
I think it's an excellent middle ground, compromise language. It's the centrist candidate of programming languages. Not the best at anything, but on average better than most.
I can compile my go application down to a single, static binary that can run in a distroless container. The packaging/deployment simplicity of Golang appeals to me much more than Python, TypeScript, etc.
Also the developer tooling is first class and sustained backwards compatibility is top-notch. I can pretty much always upgrade the version of Go 1.x I target and have 0 worries in the world. Meanwhile in Python and JS land, the dependency management problems are a nightmare.
Performance is good enough for most jobs, we're not all working on the bleeding edge, a lot of jobs are more akin to code monkeying basic CRUD
The language also seems to be built for the kind of people who think C has no downsides and everyone should write everything as explicitly as possible, which are an audience that normally doesn't get aimed at.
Now it is kind of unavoidable in DevOps space for some cenarios.
My only complaint is their approach to language design.
Inferno with Limbo, Android, Windows Phone, show that there is GC hate, and shipping products to millions of users.
I don't get the GC hate. If its done properly (like Go) its invisible for 99% of applications and dramatically simplifies things like business logic that don't need to be that complicated or fast.
The real culprit is usually Java's slow startup and memory bloat from the JVM.
Java is so bad that Kubernetes + WASM containers is basically redoing application servers 20 years later.
Are you referring to Object Oriented programming? And if so, why not?
Also, unless inheritance is what you mean by oop, it supports the other usecases of oop
There are a lot of values that goes into "performance critical stuff". For me, it can mean a chat app / money transfers etc that is performance critical but is is of course not as critical as in flight software or other system control software where GC could mean deaths.
Of course C can be is 1/3 of the speed of C, if the C is written by two different people. An average Go programmer might very well produce faster code than an average C programmer, if Go has better tools for doing normal things fast in an easy and obvious way