- Backed by a well known Company with a good image (at the time).
- Made by well known experts at the top of their field.
- Most of the risky, complex and powerful stuff is in the runtime.
- The language surface is small, familiar, conservative and consists of mostly orthogonal features.
- Very straightforward to integrate libraries and a good standard library.
- Portability and deployment are primary concerns.
- Came out at just the right time.
- Evolves without breakage.
There are significant differences between those languages, for example the JVM is a much more dynamic runtime. But I think the conservative surface paired with powerful internals is what makes it so attractive for wide adoption. It is the "blue collar" language strategy.
Languages that have more unique value propositions, lean stronger on niche paradigms and give more power to the programmers are scarier from a mainstream business perspective. I think these kind of languages have a firm stand in their respective niches and will continue to grow steadily, but will stay specialized and at the edge, while mainstream languages slowly adopt features that have been proven to work in other ecosystems.
Go is a language that belongs to the mainstream category, like Java, C#, JavaScript, Python etc. They are "Worse is better" languages that trick you into adopting some good stuff unknowingly and they all have a laser focus on pragmatism and growth.
One area in which Go lacks is its static type system. Until recently, it was practically straight out of the '70s. Static type systems are a mechanism for outlawing the compilation of programs that are known to be problematic at the expense of outlawing comparatively few good programs — a worthwhile trade-off for a language meant to be used in industry, especially when writing complicated code.
It's a shame because they absolutely could have built a better type system on the backs of all the advancements of the past half-century, but deliberately chose not to due to what I can only see as being the perspective of people who had only previously used obnoxious static type system (e.g., Java's) and decided "well we don't want that, and 'that' means types, so let's provide as inexpressive a type system as possible."
Slice index expressions accept any integer type. Integer subtypes can be defined, but there is no way to define a slice type that is legally indexed with only that defined type.
An expression a.b in some unfamiliar code may denote either a struct field access, or a pointer dereference followed by struct field access. We must read surrounding code (or lean on an IDE) to know which is meant. There was a lot to be said for C's -> operator, however unaesthetic it may appear to the eye.
About that slice indexing problem I wrote a bug-report for the language specification like two years ago. The language specification itself is not clear about what types can be used as indices. Accepting int32 and similiar could be regarded as a feature of the compiler.
The problem was recognized (like a year later), but then claimed to be fixed and simply ignored. Immediately, I wrote a follow-up issue providing a concrete example how the spec could be improved. No response to that, yet. Now another year has passed.
What's wrong with "the index x must be an untyped constant or its core type must be an integer"? ("Integer" in turn being defined by enumeration in the "Numeric types" section.)
> Slice index expressions accept any integer type. Integer subtypes can be defined, but there is no way to define a slice type that is legally indexed with only that defined type.
What actually-used language did this in the 70s? What other major languages offer this today? I know it's useful, but dunking on Go for features only C++ (and Rust?) have is offensively far from GP's claim.
Ah, you're absolutely right. I rewrote some parts of my comment a few times and accidentally removed the bit that actually connected it haha.
My point was that Go seems to have managed to be successful (for some reasonable definitions of "successful") despite at least one large deficiency. In fact, it is the same deficiency for which Java's success can be said to be surprising, though Java had ~20 years fewer history to draw upon. (Java is relevant because it's what the parent comment was comparing Go to.) It is disappointing to me that Go had a really good position to provide a new language in a specific niche, but they squandered at least one significant aspect of the language design due to (in my opinion) a lack of knowledge in the relevant area. This despite being designed by "experts at the top of their field", as the parent comment noted.
One of HN's guidelines is "charitable assumption". It specifically is required toward other posters. But you might extend that charity to Go's creators.
They actually were experts at the top of their field. Assuming a lack of knowledge is both uncharitable and, frankly, arrogant. It would be better to assume that they made choices other than the ones you would have made, and did so with eyes wide open and full knowledge.
I think minimizing compile time is a weird metric to prioritize. It's essentially asking "Would I rather guarantee my program is more correct or save a few seconds each time I compile?"
I would also point out that not forbidding bugs that would be caught by a type-checker will decrease efficiency. You just won't realize it when it happens.
Lastly, the impact on compile time doesn't have to be so great to be problematic. Plenty of languages with more expressive type systems have reasonable compile times. Some do not, I agree, but I'm not asking Go to leap to the forefront of type theory... I just think they could've done better.
There is no inherent link between "number of successful compilations" and "program correctness". There is an inherent link between "the program type-checks" and "program correctness", because a successful type-check specifically means that a certain subset of syntactically valid programs have been thrown out due to being potentially problematic.
I think it has a very different timing than java. When java came out c++ was the standard and java was clearly easier (although slower). Go is not that much easier than java or c# and it is not much faster. I don't think the standard library is much better, or even better at all and when it was new it had a lot less 3rd party libraries.
Go will probably continue to grow in usage a while but I'm not certain it will pass even c# in usage.
I think there is too little to gain from rewriting java or c# code and for speed I think rust is better.
We will see what happens the next 5 years or so.
I wouldn't just say mainstream business perspective. Go's small surface area makes it a great language for a team with large turnover. What better example of that than open source, where contributors come in, contribute a change, and then leave.
* Made by really famous veteran language designers
* Backed by Google
Not saying it doesn't deserve its popularity, but most of the things listed are not necessary for explaining its popularity, and none of them (even taken together) are sufficient.
>- Made by really famous veteran language designers
- Backed by Google
Looking at decades of how various programming languages gain popularity, those proposed reasons don't seem that convincing when we look at counterexamples.
E.g. counterexamples of unknown (at the time) creators creating popular languages : Bjarne Stroustrup (C++), James Gosling (Java), Rasmus Lerdorf (PHP).
E.g. counterexamples of famous computer scientists creating languages that were not widely adopted : Alan Kay famous for Smalltalk but Squeak is not widely used, and Niklaus Wirth famous for Pascal but later Oberon not widely used.
I think Go's popularity is mostly explained by technical reasons:
1) compiles to a single executable that's easy to deploy. This is a compelling advantage over Java,C#,Python,Ruby that require runtimes or complicated virtual environments.
2) a good enough standard library that's useful for quickly programming middleware type of apps on servers. Server-side infrastructure apps are Go's sweetspot. Go's a better productivity baseline than C++ and Javascript with their bare standard libraries that requires researching "what's the best library?" on Stackoverflow or browsing NPM repos.
3) "go routines" which some think of as the "killer feature" because that concurrency mental model is easier than threads or async/await.
I'm guessing those 3 tech reasons attract more programmers than people that think "Rob Pike and Ken Thompson are famous guys at Google so I'll use Go". Regardless of celebrities, the language itself still has to have some compelling technical advantages for it to grow in usage.
C++ was born at AT&T, shared the UNIX throne with C, adoption grew from there.
Java was created by Sun, was remarkable in having the JDK available as free beer in the age of comercial compilers, Sun bankrupt themselves pushing Java everywhere.
PHP provide a saner way to use a Perl like language on ISPs, whithout the mess of mod_perl, while most ISPs would charge extra for something else.
Smalltalk was gaining adoption, before its main backer outside Xerox (IBM) decided to join forces with Sun and Oracle, and move into Java instead, famously rewriting their flagship product into Eclipse. One of the main architects behind this effort is now leading Visual Studio Code development.
Compiling to single executables has been the way compilers worked before dynamic libraries became widespread in 32 bit platforms.
My email is in my profile. You wanna record a podcast or something? Your breadth of knowledge on the history of a lot of this stuff is really great. Have you written things down anywhere other than HN comments?
I would also add that the tooling is very good. A few examples:
- Built-in test suite that is simple but extensible. Also fast because it can test different packages simultaneously.
- Building is easy. Unless you're doing something unusual, you probably don't need a Makefile or any configuration, you just run go build .
- Gofmt means that everyone's code looks the same and you don't have to waste your time arguing about indentation or whatever. Some may see this as a downside.
I think there's another big reason: simplicity. The language spec is very short and readable, and there are very few concepts to learn to be productive with it. Compared to most other popular general purpose languages, this is a refreshing–if at times frustrating–quality to have.
>You can deploy c# app without having to install anything.
The C# option of self-contained executables is very recent with VS2019 & VS2022 and was not available when Go came out in 2009.
Before that, you had extra steps of ClickOnce installer deployment or obscure AOT experiments that nobody was using in production. (Also as trivia, the new C#/NET6 self-contained executables don't work on Windows 7 and Server 2012. You still have to install .NET Framework runtime for those older systems.)
So during most of Go's history, the C# executable would get the following error if deployed on a computer without the .NET Framework runtime already installed:
Many go apps are fairly large as well. Most of mine start at 10 MB and quickly reach 70-80 MB for fairly simple functionality for similar reasons (hosting runtime).
"1) compiles to a single executable that's easy to deploy. This is a compelling advantage over Java,C#,Python,Ruby that require runtimes or complicated virtual environments."
A.k.a.: Why just have a single thing (a statically compiled binary), when you can have several moving pieces and different levels of infrastructure and configuration to worry about (the hypervisor, the container runtime, the container cli, the open ports and shared volumes configuration, the host OS image, the JVM inside the image, java memory and gc tuning, and so on)
Maybe you are building a standalone utility in Go that can be downloaded as a single binary. Great. Most places I work at, deploy to Kubernetes as docker containers
Given that the context on this subthread is how a benefit from Go is that it "compiles to a single executable that's easy to deploy. This is a compelling advantage over Java,C#,Python,Ruby that require runtimes or complicated virtual environments."
I fail to see how this information about "most places you work for" is relevant.
Even if that's the case, you can always also deploy Go with kubernetes and whatever.
But you can't deploy most of the others as a single static binary.
(Getting one out of Java, for one, requires some half-arsed non-really-supported solutions, whereas getting one out of Go is the default).
"I fail to see how this information about "most places you work for" is relevant."
I can spell it out. Where is I work is a web based business and those businesses are typically using hosted environments. Go binaries aren't an advantage in these environments.
One can, and many do, just deploy a single Go binary into those "hosted environments". There have been a couple of posts on HN of teams doing that.
In fact one can even do it your way, and use kubernetes and co in those hosted environments and Go binaries would still be an advantage -- because the container for the go-based service can just have a static binary inside, and be relatively easier to manage than a Java one.
What other people actually use matters a lot though. Hell, a greater proportion of Java devs ca. 2002 probably knew how to AOT-compile their programs than do today. Using minority tooling in a popular language is often just as painful as using a minority language.
The availability of a half-arsed, hardly supported, restricted compared to regular JVM based runs feature, dumped at some point by SUN so that they could say they also have it, doesn't mean people should use it, or that a platform is as good in that aspect as another who has that feature as a fully supported, first class, default mode.
Don't be excited by mere presence of a feature. Implementation, maturity (which is different than "age of introduction"), completeness, support, and usage, matter...
Ah the proof of not have the slightest idea of what you are talking about, given that those commercial AOT features were never sold by Sun in first place, with exception of Embedded Java deployments.
If we go down the implementation, maturity route, than even there are several half-arsed, hardly supported capabilities in Go compared with the JVM ecosystem, even after 10 years of existence.
>Ah the proof of not have the slightest idea of what you are talking about, given that those commercial AOT features were never sold by Sun in first place, with exception of Embedded Java deployments.
Didn't wrote sold, said "dumped at some point by SUN so that they could say they also have it".
But thanks for the ad hominem.
>If we go down the implementation, maturity route, than even there are several half-arsed, hardly supported capabilities in Go compared with the JVM ecosystem, even after 10 years of existence.
Sure. Just not related to the ability of building a static binary.
Except a Java container running a simple REST server is going to be a few hundred megs, while a similar Go container will be around 10 megs most likely.
Which doesn't matter all that much until you're distributing an app made out of 10-20 such services...
That's only true if your project and all your dependencies are modularized, right? I moved on to Go around the time Java 9 had recently come out, so no idea how well the ecosystem has evolved in this direction in the meantime.
For the record, I miss many aspects of Java, especially the language and tooling, but Go was definitely the right choice for our project at the time.
From what I've seen major Java projects are still delivered in large containers with a full JVM (ElasticSearch, Keycloak at least).
Many projects choose the easy way out when packing their deliveries, and to certain extent Java is having a Python 3 moment with anything past Java 8.
The cynic in me sees that as the main reason why Docker was adopted, HP-UX was already having containers in 1999 and no one was rushing to package Perl into them.
Every Java app I've ever deployed, I needed to tune the JVM.
Well, not when I'm running something locally. Every app I've deployed professionally in corporate environments (which is most of my experience running Java), I needed to tune the JVM.
I'm surprised. Latest JVM versions are tuned really well out of the box. Tuning is a good thing by the way. Its the reason Java can handle areas that Go can't.
In my case "backed by Google" was a deterrent, not a feature.
I gave the language a chance after trying Rust (backed by Mozilla - which was a feature to me ;-) and I found it easy to start.
Go is very well documented: That was the killer feature for me.
No more search tutorials / videos etc. - just get the go book, read it, and start coding.
Of course there are tutorials and videos everywhere for fun stuff.
But good documentation is more important than we think - even in the 21st century!
To me, in the old Go vs Rust debate, there are two things that are abundantly clear in making a compelling case for Go.
First, I don't think even the most devoted rustacean can deny that Rust has a hell of a learning curve.
But perhaps most importantly is that Go has a strong and extensive standard library that covers many 21st century applications (e.g. talking to REST APIs).
The problem to me with the Rust "no stdlib" model is it leaves you with two equally unattractive options:
1) Write the library yourself (and leave yourself with the associated technical debt of maintaining it)
2) Figure out which of the often dozens of third-party Rust crates you want to use (and rinse and repeat the selection process for every library, and then expose yourself to third-party maintenance debt).
The most interesting thing about the go vs rust debate is that it happened. In hindsight it seems abundantly clear that they aim for entirely different fields with negligible overlap, almost as if you'd lump together tennis and golf because they are both ball games with a somewhat upperclass bias ("how different can they be? And I hear polo is the same but with horses!").
But back then? Yeah, I was kind of expecting one of them to "win".
They overlap way more than they don't i.e. there is way more software that you can write in both languages than software that you can write in only one of them.
The "best language for the job" is mostly a myth.
The choice of language is mostly dictated by what you cannot do, rather than what you can do.
Can I use Go or Java to program a micro-controller with 128 kB of RAM? Not really (at least no using the official, non-crippled implementation) because even "hello world" in those languages exceeds that 128 kB limit.
If I'm writing a cmd-line app that I want to ship as a single binary for Windows and Mac and Linux, I'm not using Python. Technically it's possible but very few are doing it while Go gives me out of the box multi-platform compilation.
The reality is that the majority of software written today falls into one of those categories:
* web frontend, running in the browser, by necessity written in JavaScript or something that transpiles to JavaScript. Both Go and Rust are out of this game
* web backend and similar server software: both Rust and Go compete for that
* command line apps : both Rust and Go compete for that
* games : AAA games are pretty much C++, Go and Rust are out (although Rust could, in principle, work)
So in most cases both Rust and Go are unsuitable for the task or they compete for the task.
> Can I use Go or Java to program a micro-controller with 128 kB of RAM? Not really (at least no using the official, non-crippled implementation) because even "hello world" in those languages exceeds that 128 kB limit.
You'd be surprised actually. Java Card is actually designed for memory constrained environments. It's not as featured as Java itself but it uses the same language syntax and class file format.
There you have TinyGO for embedded and wasm stuff, but it is not the same as using the same language and tooling everywhere like Rust. I like Go and a fan of Rust but for Rust,some standard libraries lagging like async and having alternatives to choose from makes me uneasy about Rust in general (tokia vs async libs e.g).i am just a beginner in Rust so i might be wrong. The game engines in Rust are way cool btw.
This hasn't been a big issue for me with Rust. You do have to spend a bit of time looking around initially, but there are lots of good-quality libraries that aren't going away anytime soon, you make your pick and move on and after doing that a few times you pretty much have a standard library of sorts. For me personally, that wouldn't be a reason to pick Go over Rust.
What's moving the scales in favor of Go, for me, is Rust's borrow checker. I'm aware that it has a bunch of advantages over a garbage collector, but those are paid for with a pretty noticable productivity hit that doesn't seem to go entirely away with experience either; experienced Rustaceans I've consulted with less-common patterns still spent a lot of energy finding a way to make them work with the borrow checker and still sufficiently efficient, and most of that could have been saved for more productive work in a language more open to existing design patterns. Usually I'm neither out for the maximum safety at all costs nor resource-constrained, so I'd rather take Go-ish levels of safety and Go-ish performance and get work done faster.
If there was a Rust with a first-class garbage collector, but keeping all the neat functional elements, the neat semantics, the great libraries and ecosystem, strong types, single binary etc. pp., I'd pick that right away. Go is "easy" at the cost of expressiveness to a degree that makes for reams upon reams of repetitive code or code generation, and Rust-ish functional patterns could greatly condense that and make much more readable, at the expense of having a somewhat higher learning curve. That's a trade-off that I'd much prefer, reading and reviewing Go codebases can be very tedious.
Unfortunately the lack of investment in the standard library for important things like structured logging have meant that there is still a bifurcated ecosystem around things like “what logger does this use?” (rather than “what async runtime is this for?” in Rust).
Unfortunately major projects pull on tens of random libraries from the internet which represent real supply chain risk.
The API case for Go is absurd IMO because what libraries are there in Go that are simultaneously not widely available in other languages and also difficult to implement on your own?
People complain about Racket's ecosystem, but it has many libraries that would be PhD level effort to implement and are unique in its ecosystem such as Rosette and Redex. If some random REST API doesn't have bindings yet, implementing those myself isn't all that difficult.
Both of those libraries look cool, but I'm guessing that most of the users of Go would not need them. I definitely agree that I'd rather have to write API glue code than a constraint based solver for a project that has time constraints though.
And those two options don't strike me as equally unattractive. Writing everything that isn't in the standard library from scratch is completely impractical for modern apps. Nobody does that in Rust. Integrating crates from the ecosystem into your workflow is just part of developing in the language.
So put them in the standard library or have an organization that guarantees support for the next 10 years. The Rust community doesn't really understand why languages with a standard library have one. It isn't about performance or ease of use, it's about making guarantees about technical debt.
Using the two examples go and rust, Go's documentation is on another level compared to rust, it's more common to see examples in Godoc's than in Rust documentation... That's not a failure of Rust or the maintainers, it's just a different culture I guess.
If I want to do something in Go with a new lib, i can easily put together what I need to do using the documentation.
Where as with Rust, it's often confusing to the point where if they don't have an examples folder on the library, I'm shit out of luck understanding how to do something.
I don't think Go's documentation is better than Rust, Go is just a lot simpler than Rust. Especially if you are a programmer with a background in any of the C-ish syntax languages (C,C++, javascript, Java, C#, etc), its just really easy to pick up.
Rust is a mind bending ordeal by comparison with both the borrow checker and other foreign ideas that take a while to come to terms with.
> I don't think Go's documentation is better than Rust, Go is just a lot simpler than Rust.
Having used both I disagree; Go's stdlib is extremely well documented, even unexported types are along with examples etc. Rust docs are useful but more often feel like there's many things you're expected to figure out from the source and only minimal examples are given.
I am a fan of Rust, but I think Go's docs are an example to follow. The more complex the language, the richer docs it should have imo.
Quite aside from docs, Go's tooling situation is also better.
They both have good patches of documentation and bad ones. They're both better documented than, say, Ruby. Go has multiple edges, not just simplicity, but also a larger user base. You couldn't reasonably disqualify either language basd on their documentation. Certainly, Go is easier to pick up than Rust, but nobody's arguing that.
Note that Golang is older than Rust. When it came out it made a splash, despite not having any books or videos yet, despite not having any libraries available yet. It didn't die in obscurity (like someone else's "Go" language that existed before!) precisely because it had names of Rob Pike & Google associated with it.
Yes! The "killed by Google" meme is young. Back in the days it was like "i want to be like Google" (ignoring the fact that most people don't have scale like Google and very different problems) and anything out of Google must be good!
Google also can't really "kill" Go. The license doesn't permit it. They could stop supporting it, at which point the community may or may not pick it up. (I'm inclined to think they would, but I can't guarantee that.) They could try to drag it in some hypothetical super-Google oriented direction (integrating Google Cloud somehow deeply into the language?) but they haven't yet, and at this point, again I think the community would fork and move on.
It's not a service they can pull the plug on, it's a software package that would still exist even if the entire Google organization went poof tomorrow. Because if it was a service they could just pull the plug on I would never have started using it.
I can't judge, as I have neither any insight into the development structure (how many non-Googler so relevant work) nor complexity (how many understand the deepest details of the compiler etc.) but I have seen different Open Sources Projects die a slow death after the primary developer went way. Everybody depended on the "free" labour being done and once gone one couldn't find agreement on how to go on. But yes, Go's spread is big enough that it won't immediately die and Google would probably be responsible enough to transfer to Linux foundation or ASF or somebody who can help to organize a new structure.
Anyways, key point was that Google reputation was different, when Go took up. I can imagine if it would launch now it would find different reaction, which could prevent a community forming, thus less of safety.
It still is. Google may be killing off its site-products, but not its own software. A lot of open source software Google made for its own consumption (Kubernetes, Tensorflow, etc.) has become pretty much industry standards, despite everyone saying they're a lot more awkward to use outside of Google than inside.
The documentation is a big point, but to me, two other points are just as important, maybe (probably) more so:
1. The standard library is very good in the sense it covers a fairly wide range of areas and gives you some idea of how to use Go idiomatically (I feel this is more important in Go than in other languages I've used).
2. The language just feels right to me. I have not met any other language that feels like it was optimized for my brain that well. I recently made an attempt at learning Rust, and I kind of got it, but I eventually gave up because the benefits did not seem worth it to me in light of the steep learning curve. Go just clicks with me. It's not the best language ever by whatever metric you choose, but for my needs, it is the right language.
Google doesn't have the best track record of maintaining their projects, but I've had a similar experience with Android/Kotlin. Always had a dislike for "strong" OOP, but then had to do a small android app for a university project, and the tutorials, documentation and tooling for Android with Kotlin were pretty amazing. This took away most of the problems of understanding the syntax/language and gave me the leeway and motivation to get a better understanding of the concepts. My dislike for OOP is now at least partially cured.
Surprised to read that! Android has that "initialization through mutation in a set of lifecycle callbacks resembling plate tectonics" so deeply baked in that even kotlin just shrugs and learns to love the lateinit. I consider that a prime example of how OOP can lead one astray.
I suspect that documentation quality is part of "by veterans", people old enough to have a considerable part of their programming biography set in the days before Google driven development. Slightly ironic.
For me, Go solved a lot of issues that I've had with both C and Python.
C is a nice language because there's no magic happening - functions are only executed if they are explicitly called. However, C had problems with strings, memory management, resource cleanup, undefined behavior, and probably a few other things I can't recall at the moment. It was also not designed with concurrency in mind, and glibc for some reason doesn't support static linking.
Python is a very nice language to work in, but there is a lot magic going around with all those Python protocols and magic methods. I also find myself making a lot of errors using exceptions - exceptions can happen at any point and there is no way to anticipate them, other than documentation, which leads to try/except boilerplate. And if I want to handle exceptions on a more granular level, I find myself writing try/except for every line I call, which is 2 lines of boilerplate - same as "if err != nil {" and "}". Also, CPython has a lot of dynamically linked dependencies, which makes containerization more difficult. There's PyInstaller, but PyInstalled doesn't seem to play well with non-pure-Python modules (uwsgi, for example). And concurrency in Python is terrible because of GIL, and asyncio is far from perfect, considering function coloring and inherent single-threadedness.
Go managed to become a language with a feel of Python but with certainty of C. It's like someone took C, fixed strings, added anonymous functions, automatic memory management, defer keyword for resource cleanup, sane concurrency model with channels and select. I think the name "select" comes from the Linux select syscall which allows you to wait for multiple file descriptors until one of them is ready - same thing happens with select and channels in Go. The select syscall (and its descendants) is the bedrock on which the whole asyncio world relies upon, so Go's concurrency design is already proven in practice.
When I write Go code, I'm rarely worrying about an exception popping out of somewhere. Panics do happen, but in most cases, they are caused by truly exceptional errors and warrant a crash.
And even though it's not a "systems language" in a kernel sense of the word, I've used Go to write video4linux applications, so it is certainly capable of making ioctls and manipulating C-like structures.
Also it's statically linked, so it's possible to make really small containers with it, and easily cross-compiled, which is nice for portability.
We can sort of evaluate of much "backed by Google" means by looking at other languages backed by Google. The main one I have in mind is Dart. Here's a few links:
Dart seems to be doing relatively well. Considering Go has more things in its favor than Dart, it's logical that it's doing better. Still, the Google boost seems to be really big.
Similar to the peer comment to me, Dart languished for a long time. You have to remember Dart was created as a replacement for Javascript and that they wanted other browsers to embed the DartVM in their browsers. This got absolutely rejected by Mozilla, Apple, and Microsoft.
They then attempted to use it as a transpiled language, but it always generated larger javascript files than most other solutions. It still exists and is used, but Typescript ended up being a better solution. (note: there is AngularDart, which is a bit of a fork/mirror of Angular, but for Dart). This has some uses within Google as I understand it, but it's usage outside of that is rather small.
Flutter using Dart ended up being a large boon for the language and drives much of the changes to the DartVM.
Dart had to go through various targeted usages before it really found a home.
And even with all those troubles, it's still doing better than many many programming language, which was my point. The Google boost seems to be real and big.
The "Backed by Google" is an under-appreciated social piece of the puzzle. It's not just that Go has institutional backing, it's that googlers produce a lot of startups, and they bring their favorite things with them, and quite often one of those things is Go.
Dart created a lot of interest at the time. The main reason it didn't take off was that Google couldn't convince MS or Mozilla to embed the DartVM in the browser.
Golang obviously didn't have that constraint, it didn't depend on any external runtime.
After the browser rebuff Google had a meandering approach to figuring out where Dart could fit in instead. Whereas Go slotted quite easily into one specific niche, building microservices at Google.
I think the lesson is that clear positioning is crucial
(Submitted title was "What made Golang so popular? The language’s creators look back". We changed the title when we changed the URL - see https://news.ycombinator.com/item?id=31571574)
I definitely think you’re too fast to dismiss the language features contributing to popularity. As an example:
Fast builds are a positive developers immediately warm to when they experience them (stand by for rustacean “i need time to make tea and my compile times are exactly the right length for tea break” type comment). The example of the 4.4mb c++ project that results in the compiler ingesting 8Gb of data is eye opening. C++ needs to resolve type information for all includes and all their includes and all their includes… go only needs the interface so compilation can be done without all that effort.
>> Made by really famous veteran language designers
> Yeah that’s a positive
No, that's also a negative. C is close to assembly and produces fast code but it's weakly typed and very unsafe. Pascal was the strongly typed and safe option but people went for C because speed was considered more important than safety back when processors were slow.
In today's online world, we've realized safety is more important than speed. We write web apps in slower interpreted languages and Rust is a response to unsafe code that can be hacked like a hot knife through butter. I consider it a move in the right direction.
So I don't consider Go being made by really famous veteran language designers to be a plus because they produced a poor language that only won out because it neglected safety in a quest for speed. That wasn't as bad when computers weren't online, but it still allowed programmers to make errors that caused code to crash. Today it's become a critical issue.
Interestingly, Go is more like Pascal, Modula-2 and Oberon than like C, except in syntax. With Go, the creators of C have admitted Niklaus Wirth was right.
I started using java at 1.4, i remember Sun shouting to anyone who would listen that HotSpot could beat the gcc of the time on some 32bit integer benchmarks. IIRC it wasn't a million miles off the pace for floating point operations either.
> Oh here we go :-) and yet the world spins on C kernels and lands jumbo jets in C autopilots and regulates heartbeats with C pacemakers and, and, and …
Keep in mind that many of those things are written in a subset of the C programming language, such as MISRA C.
Absolutely, just as there are many ways to achieve C speed in languages like Java for particular sections of code by applying non-idiomatic optimisations, there are also many ways to improve safety beyond just types. Even things like the borrow checker has decent alternatives (tsan, msan etc.) that can be used in existing language stacks.
MISRA as you point out is another useful tool in the toolbox.
The "Pascal-like" elements are the contribution of Robert Griesemer (https://en.wikipedia.org/wiki/Robert_Griesemer), who studied in Zurich and is also a co-creator of Go. The syntax has the curly braces and other C-family elements to appear more familiar (plus nobody really wants to write "begin ... end" all the time), but the declaration syntax is also Pascal-style ("x int" instead of "int x"). What reminded me most of Pascal when I first saw it was the ":=", but it has a different meaning in Go than in Pascal.
...and "really famous veteran language designers" wouldn't become famous veterans if they wouldn't learn something along the way.
You've completely mixed up two different senses of "unsafe", the one where the language is prone to idioms that cause fatal errors (which is also true of all those slower interpreted languages), and the one where a mistake means the program can do literally anything (which is not true of Go).
"Unsafe" in most discussions today refers exclusively to the latter.
Production class Pascal compilers weren't, thus the Kernigham meme about Pascal misses the point that outside UNIX and a few other systems, the Pascal dialect people were using was as capable.
Likewise outside UNIX, the C compilers that were starting to appear were just as fragemented, supporting only subsets of K&R C.
I really dislike this meme of pointing out that Google has deprecated a lot of projects. Do people actually expect Google to staff people & resources running every project they've released forever?
A more interesting comparison would be open source projects that Google has abandoned or failed to properly hand over control of to the community, especially if we're talking about Go.
It’s not clear to me that Go would survive Google giving up its continued investment.
Go has the fundamentals to survive - it’s open source, it has a healthy amount of contribution from non-google employees, the compiler is written in Go (that’s important when you consider an alternative situation like a python or js developer who wants to contribute a change to their compiler (they need to learn c / c++ respectively), i strongly suspect that if google walked away tomorrow, the velocity of change to the compiler, stdlib etc would not massively drop in the short term.
Medium / long term though… would i bet on Go over Java? It’s not clear to me that Go has reached the level of market penetration to make that a simple question.
Edit: i meant to add halo projects like docker, kube etc. as reasons to suggest the Go community is healthy
I think we have some models of what would happen to Go without Google, it's probably similar to what happened to Java under the weaker period of Oracle's stewardship.
The tool as-it-is keeps chugging along pretty well and even improving in small ways, but it stops reacting to larger trends and misses the boat at critical moments. Some new language in the same space comes up and finds it easy to shear off a massive portion of its user base by doing "the same thing, but modern".
(Less obvious models would be PHP to backend JS, and PHP and Python to Go, which had similar community development arcs.)
It is true that Google has some poor product management and has some hilariously inept examples or product coherency (chat being the biggest disaster). But people praise startups for pivoting (read: killing a product) and (in general) demand innovation over glacial iteration. Trying new stuff necessarily means killing things that don't work (or paying a whole bunch of engineers to maintain a dead product for eternity).
Yes, but you discount the size of Google. Some of the things Google has killed have been large enough to have been considered successful products for a startup. They kill a "tiny" product because it's only large enough to be what some startup hopes to become. Google Reader is my favorite example of this. Multiple companies now exist in the soil on top of that grave.
The CTO dictated our move to Go two years ago on what felt like a combination of whimsy and anti-Microsoft sentiment. I'll admit that there are parts of the language that are nice, such as the relatively snappy compile times and single statically linked binary output, but not a single day goes by where I don't miss C#, and more specifically .NET Core (now just .NET I guess?), which can do everything Go is doing.
Like Go, C# has also always been a decade behind on the tooling side. For a recent project I wanted very fast HTML templating and I/O. Went with C# instead of Go and it's looking pretty good so far. The tooling is close to the level Ruby was ten years ago, and that was really acceptable. I was very happy with my previous project that I did in Go as well, you just can't go wrong with Go for implementing network protocols.
If you need more than a microservice, then you need more than Go in my opinion, and C# is an excellent choice. I think most of these startups going mono-lingual on Go are going to regret it, just like the startups that went mono-lingual on Node.js a decade ago.
If you're building anything that requires some serious architectural structure, and that might be easiest to implement as a monolithic app, then you need a language that supports that instead of getting in the way. Now with Typescript Node.JS might finally be suitable. But I'd definitely consider Ruby and C# or maybe Java or even Haskell first. Maybe Elixir, I heard that's still going strong as well.
Why people always mention tooling but never explicitly mention which tooling they miss? I use Java for 4 years and I constantly find stuff that's missing here where other languages have it baked in from day one
Not the other person, but I miss Gradle every time I use something else. It feels like the correct tradeoff of complexity and power. The Bazel family always felt unapproachable, and things in the Python or Rust universe basically require a makefile or other orchestrator to make sure tasks are ordered correctly.
What do you find missing from the Java tooling world? In my experience it’s been the best built out, and maybe overly so.
Ah interesting, so I'm relatively happy working with C# and .NET. I'm interested in what you think might be lacking, is there an example of another language with some tooling not available in .NET?
Note: not trying to pick a fight, I'm legit interested what I might be missing since I feel like my needs are pretty much covered :)
My .NET experience is about 1 year out of date, but at the time the ecosystem was in a really great spot. First class Linux and Docker support, your choice of editor/IDE with VS, Rider, and VSCode, and nice test and profiling utilities.
Historically though (pre-.NET Core), .NET was always in a Microsoft bubble which held it back as the industry consolidated on Linux and Docker. The person you're replying to may agree that C# tooling is currently pretty good.
Yeah, the language itself has never really “clicked” for me, and I've tried a few times. It still feels cumbersome to write. The tooling, standard library and fast compile times are really great though. Maybe I'll revisit it.
> - After Docker and Kubernetes explosion, all Cloud Native Foundation projects start using the same language, thus adoption
This take sounds highly unrealistic.
No one in their right mind would ever say "well Docker/Kubernetes were developed in Go, thus that means it's a good idea to develop a totally unrelated application that bares no resemblance or shares any use case in Go as well".
Also, migrating away from an interpreted language to a compiled one to develop performance-minded applications does not mean that the compiled language is suddenly spectacular. It just means the initial proof of concept ran it's course.
> No one in their right mind would ever say "well Docker/Kubernetes were developed in Go, thus that means it's a good idea to develop a totally unrelated application that bares no resemblance or shares any use case in Go as well".
I agree that this take sounds silly, but in practice I've seen it play out just like that. So many projects centered around CloudNative seemed to have picked Go simply because it's the language used by many other leading CloudNative tools. GoLang == the cloud native language according to many folks.
The amount of Go projects in Cloud Native Foundation shows otherwise.
Most people pick languages based on platforms, not a language in isolation and go hunting for projects.
As for the point migrated to a compiled language from Python, if it wasn't for the shinny thing, the migration would have been to a compiled language with proven record in prodution like C and C++, as it is common on the ecosystem.
And regarding Java, everyone that actually knows the ecosystem is aware of AOT compilers since 20 years now, even if they have been available as commercial only for the most part.
> The amount of Go projects in Cloud Native Foundation shows otherwise.
That says nothing at all, actually.
Beyond the transparent appeal to authority, why would anyone take decisions seriously when they are made without any technical merit in mind and just follow a mix of cargo curlting and pushing in-house tools, such as the case of the kubernetes migration to Go?
> Most people pick languages based on platforms, not a language in isolation and go hunting for projects.
The whole point of this discussion is that people don't, and make decisions without any technical merit in mind.
> As for the point migrated to a compiled language from Python, if it wasn't for the shinny thing, the migration would have been to a compiled language with proven record in prodution like C and C++, as it is common on the ecosystem.
This personal assertion ignores the fact that there are plenty of alternatives that considerably improve over C++, let alone C (?!), not to mention that it reiterates again the mindless cargo cult mentality behind Go.
> And regarding Java, everyone that actually knows the ecosystem is aware of AOT compilers since 20 years now, even if they have been available as commercial only for the most part.
I don't understand what point you tried to make with regards to Java, specially as the Kubernetes migration from Java to Go was pushed by people who worked on Go, and thus it had an unavoidable self-serving "eat your own dogfood" aspect to it.
> This personal assertion ignores the fact that there are plenty of alternatives that considerably improve over C++, let alone C (?!)
While it is easy to improve on C++ it's proven difficult to improve on C[1].
C++ is an exceptionally large language, with lots of features that interact in subtle ways which trip-up even experienced programmers from time to time. It includes all the footguns from C, and adds an order of magnitude more.
C is a dead-simple language with only a few really dangerous footguns (which are also present in C++), mostly related to memory errors (corruption, leaks, races, etc).
I view C++ as "C with more footguns".
I view Go as "C without the memory error issues".
It's not really comparable to C++ because it is a better C, not a better C++.
[1] I think that only Go has managed to improve on C.
There's a number of things at work in these situations, but I people who start out and/or want to work for Docker are highly incentivised to learn Go, and have a Job with Go in the description. In the current job market, if developers want to use a specific language, it is often times a good idea for companies to just go with that language, even if it isn't the perfect fit for the project... And then again, project leads aren't immune to hype either, a new, popular language will be used more, simply through being hip and attractive.
> And then again, project leads aren't immune to hype either, a new, popular language will be used more, simply through being hip and attractive.
Resume-driven development does sound like a key factor, even in the decision by Go advocates in Google that pushed for Kubernetes to be rewritten in Go.
But somewhere along the line people are forced to consider technical aspects.
There is a well known article (which I am totally blanking on) arguing that many successful programming languages are the Native/System Languages of a major platform.
So C is the System Language of Unix, Javascript is the Native Language of the Browser, C++ for most operating systems.
Kubernetes and containers are a major platform. You could say the System language for it and related projects is Go.
"No one in their right mind would ever say "well Docker/Kubernetes were developed in Go, thus that means it's a good idea to develop a totally unrelated application that bares no resemblance or shares any use case in Go as well"."
I guess there are a lot of crazy people out there because I've heard this mentioned numerous times.
Yeah, I do agree that it's not a smart thing to say. But nearly all the times I saw somebody picking a platform to standardize on, they have a similar rationale.
I guess there are just no good reasons for choosing one platform over another to standardize a team. Or people that insist on standardizing tend not to act on good reasons.
Kubernetes never really migrated, the first prototype were built in Java but the real first version that released were in Go, so it's not a migration, the poc were in a different language.
But nobody is talking about the technical merits of that switch or of Go, we're talking about the popularity of Go. If tomorrow I create a language called "Gorilla" that is a worse language than Go, that Kubernetes switches to Gorilla and that Gorilla gets popular, there's a good chance that the switch will help the popularity of Gorilla. If instead I create a language called "Whale" that is a better language than Go, and the same thing happens, again the switch will have helped the popularity of Whale. The exact same thing will happen with a language exactly the equal of Go. All of that to say, technical merit has nothing to do with it, it was never the subject.
Well it's pretty clear 10 years ago than Java would have been a disaster, imagine all the controle planes + pods + side cars etc ... running on the JVM, you would have needed 20x more memory.
Even to this day JVM memory consumption is way way higher than Go and it would make no sense to use it in Kubernetes.
It's resources than workload could not use meaning higher overhead for Kubernetes which would reduce adoption.
> Well it's pretty clear 10 years ago than Java would have been a disaster, imagine all the controle planes + pods + side cars etc ... running on the JVM, you would have needed 20x more memory.
I'm not sure if you are aware, but the web runs on Java.
Android is also Java, thus even the people in charge of developing one of the most popular resource-constrained devices in history disagree with you.
Beyond desktop (specially games, except Minecraft), front-end and embedded devices, you'd be hard-pressed to find any class of applications whose bread and butter does not involve the JVM.
Even desktop, Microsoft is heavily invested in C#, which was the company's answer to Java and dubbed "an imitation" and described as "(..) sort of Java with reliability, productivity and security deleted."
Android is C/C++, or maybe you mean the app that you deploy on Android are built in Java right?
I stand my point, the JVM is not the right tool to build components for Kubernetes because Kubernetes needs lots of small service running everywhere, running those in the JVM would have resulted in large memory consumption.
You can try yourself, build a very simple hellow world web app with the most popular JVM ( Oracle one ) on version 8 for example, you'll see how much memory it uses by default.
It really isn't, and frankly this sort of comment makes it quite clear how uninformed you need to be to make this sort of claim. I mean, even the Android NDK specifies quite clearly in its own description that it's only designed to offload parts of an Android app to C++.
In the Android projects I worked, the Android NDK was only used to implement small performant components that sat on the hot path, such as image processing work. Even so, the experience was not exactly on the happy path.
> I stand my point, the JVM is not the right tool to build components for Kubernetes because Kubernetes needs lots of small service running everywhere, running those in the JVM would have resulted in large memory consumption.
This personal assertion has no bearing in the real world. Not only do we have high frequency trading apps developed in Java but you're also succumbing to absurd beliefs that you get architectural wins for free by switching the programming language.
Also, it's absurd to make clams about the needs of running "lots of small services" when the web is already served by "lots of small services" developed in Java with non-performant web app frameworks, which are subsequently ran by the likes of Kubernetes.
esbuild [0], a JavaScript bundler, has made waves in the frontend community over the past couple years for being orders of magnitude faster than alternatives and written in Go (as opposed to Node.js which is the usual choice for obvious reasons).
GoLang works for my team because it's boring, small, compact, not fancy, easy to pick up and start writing real production code in less than a week. It hits the sweet spot with regards to language constructs, performance, features, superb documentation, and a de-facto set of practices and design principles that make it easy to pick up a completely new codebase and understand it very quickly.
It works very well with VSCode and even better with IntelliJ IDEA, debugging is painless, and it even runs on our Raspberry PIs and other IoT devices. We use GoLang on a whole bunch of MIPS and ARM devices, it's a great option seeing as how quickly we can get production code up and running on small edge devices, routers, etc.
Sure, we can write embedded code in C, but GoLang allows us to roll out new features three to five times quicker.
* rich standard library, particular for internet facing apps
* "simple" language
* single binaries
* massive corporate support
* rich or full toolset
The first and second point fortunately "coincided" with: the move to multi-core chips, and the "second" dot.com boom of the 2010s. Which you could probably attribute to the rise of (Google) Chrome, and the decline (finally!!) of IE6, which held back a lot of "innovation".
This reads exactly like the joke where successful people describe their daily routine and one of the items besides things like running and meditating once a day is "my parents are millionaires".
The concurrency is "easy" in that the syntax for spawning a thread is simple... but that's kind of it. Like other languages, it has a concurrent queue abstraction, and it has some syntax sugar to make using the concurrent queue nicer than some other languages. But like other languages, you end up in concurrency hell with mutexes and condition variables and semaphores and deadlocks.
It has a concurrency story that's about as good as the likes of C++, and inferior to Rust (which errors at compile-time if you do something dangerous) or JavaScript (where the core event loop makes concurrency less necessary and concurrency is achieved with multiprocessing).
In my experience, debugging concurrent Go is way harder than debugging concurrent C++, since the cheapness of spawning a new thread makes people much less careful about their threading model.
Strongly disagree. Yes, it is not a free lunch but they have made several deliberate decisions. If you code your Go like you would C++, you are not using the language in its intended fashion.
They have nice features like a data race detector and deadlock detector.
Channels are not just a concurrent queue, they have nice deliberate things built into them. They are based off of Communicating Sequential Processes (CSP), which has influenced other languages like Rust and Erlang as well.
Green threads are very cheap, and therefore remove yet another thing to think about when using threading. They have made good decisions around the memory model for them as well.
When I worked in C, the first thing we’d do in a new program is introduce a green thread-like scheduler so we could achieve concurrency. Then achieving parallelism is as simple, heh, as bumping up the number of worker threads and fixing the data races. Go handles both of this for you from the start.
So sure, when you are aware of sound multi threading design, know what TSAN is, and have a lot of experience with C++ you can look at Go and scoff and say Rust is better.
But for 90% of the programmers I meet in my career, especially those who grew up in the age of the internet, they do not have experience with this and greatly benefit from Go.
I am in probably one of HN’s “most coveted” engineering companies, and barely anyone has worked in largely multithreaded programs. It is such a problem that we are now splitting services into processes to avoid handling multithreading.
But over in our Go-world this is just not a concern. Seriously, Go is designed really well for backend services. I used to hate on it a lot, but after working at larger tech companies I have bought into it more for those use-cases.
> fixing the data races. Go handles both of this for you from the start.
In what sense does Go handle (prevent) data races for the programmer?
In my experience (which is not _extensive_ but certainly non-trivial), Go programmers deal with all the same problems of shared mutable state that programmers of concurrent code in other languages deal with. Sure, mantras like "Don't communicate by sharing memory; share memory by communicating" are wise, but it's just a mantra, not anything the language provides for you. A skilled concurrent programmer will write code in this manner regardless of the language, and Go doesn't provide a ton as far as enforcing this.
Sure, you _could_ write your go program without any shared mutable state, but that gets convoluted fast.
"Like other languages, it has a concurrent queue abstraction, and it has some syntax sugar to make using the concurrent queue nicer than some other languages. But like other languages, you end up in concurrency hell with mutexes and condition variables and semaphores and deadlocks."
It is true that technically, Go does not force good multithreaded code. What it has is good community practices, and libraries that work with those good community practices.
And there is a good case to be made that a stronger language (like Rust, or Erlang, perhaps Pony) is still necessary to really make multithreaded code take off.
However, if you got yourself caught in "concurrency hell with mutexes and condition variables and semaphores and deadlocks", it is because you weren't programming with the community's best practices.
I mean, I know there's a certain vacuity to "just do it right", but in this case, you really didn't do it right. And maybe you would be better off in a language that wouldn't permit you to do it wrong (Erlang, Pony) or a language that tells you to stop it you can't do that (Rust), but there was almost certainly a better way to get it done.
I'd add "well designed" to the standard library point. When I first started using Go, one of the things that struck me was that not only was there tons of standard library functionality to do things I'd normally have to install 3rd party modules for in other languages, but those standard library modules (mostly) had well-designed, easy-to-use, and consistent interfaces. Mostly. I'll still never forgive them for making crypto.PublicKey an empty interface.
I haven't used Go in a while, but I remember there was some pain when `Context` began being used for a lot of new APIs but couldn't be introduced to older APIs for compatibility reasons. I also had some frustrations with what seemed like overfitting with standard libraries interfaces, e.g. the interface for closing something returning an error, so then every `close` method would return an error even if it was always nil (which stuck out more to me given that interfaces in Go are implicit, so it wouldn't really be that big a deal to just have a separate interface for closing things without returning an error and no code would have to be changed in all the places that would use it).
What I'm more interested in is the comparison between the cases of Go and Dart, which both are languages developed by Google.
Why Go is so much more successful (in the system programming domain) than Dart (in the web/mobile/desktop domains)? Many of the listed good choices (e.g. being developer-focused) can be (had been?) applied to Dart as well.
I'm planning to write a blog post with my experience with those two (I'm using Go full-time for 8+ years and Dart for Flutter for more than 3 years). Those two languages are on the opposite extremes for me (minimalistic vs packed-with-almost-every-feature-known). I use Dart because Flutter is amazing, and Flutter and Dart teams are closely cooperate to my knowledge. I still struggle from time to time to navigate over 100500+ ways to initialize things, or rewriting seemingly innocent map/filter/foreach loops into "normal" readable `for (var i := ...` loops, and generally trying to apply lessons of readability from Go to Dart code as well.
Also, I did a thought experiment a couple of years ago on how Flutter would look like if it was built on top of Go [1] (it doesn't capture all the surface of Flutter, but that was my level of involvement with Flutter by that time).
Anyway, thanks for reminding about idea of writing blog post on those two.
First Chrome was placing it as JavaScript replacement, which made its adoption a failure from other browser vendors, similar to what happened with PNaCL.
After the project's dimissal, it got rescued by AdWords team that had just migrated away from GWT into Dart, and surely wasn't willing to drop it on the floor.
Then Flutter kind of gave it a new purpose, and by then most of the original designers had left as they were against the new direction of strong typing, and I guess how everything was managed to start with.
They have found a place in Fuschia, yet the Android team is also quite keen in making ART run on top of Fuchsia, and it is no surprise the Jetpack Compose is Flutter in Kotlin.
Because Google announced that they will add Dart VM to Chrome, and web community's reaction was "Hell no, we've just got rid of VBScript from the Web Platform, and we don't want vendor-specific languages".
Google changed course to using Dart-to-JS cross-compilation instead, but their initial implementation added 700KB+ of boilerplate at a time when people debated whether 100KB jQuery is too big.
I think the issue was, what was dart useful for that JavaScript or typescript didn't already solve? You had a new language that needed a separate VM to execute that offered basically nothing that typescript/JavaScript didn't already offer. There was no compelling reason for it to exist apart from "just because" - I think that had typescript taken off a few years earlier then they'd probably not have bothered with dart.
Go brought something new that answered an issue developers were facing: easy concurrency in a high performance garbage-collected language that compiled to a single binary with no dependencies. C/c++ did not offer that, nor did java, nor did python. Go filled the gap in the market.
Not to turn this into a language debate, but I think it's worth pointing out that Dart is a completely new language that has a more succinct syntax and more sensible semantics than JavaScript. TypeScript is different in that it intentionally is just JavaScript with type annotations. That makes TypeScript easy to adopt but it also means it inherits a lot of JavaScript's flaws.
For example, in TypeScript you still have nonsense like "this.method = this.method.bind(this)" while in Dart, method tear-offs just work. In Dart it's trivial to implement classes with value semantics that can be used as keys in a Map or Set, which is basically impossible in JavaScript. And so on.
I think most people would agree that Dart is just a much better language than JavaScript or even TypeScript. So the succcess of TypeScript is best understood as building on JavaScript's existing popularity.
> I think that had typescript taken off a few years earlier then they'd probably not have bothered with dart.
I always suspected that Google's investment in Dart was related to the Oracle lawsuit over the use of the Java API in Android. Remember that Dart is also the language behind Google's cross-platform app framework Flutter, which was developed while the Oracle case was still in court.
I suspect that Google wanted to ensure that for Flutter they used a language and API that Google unambiguously owned the rights to, to avoid another debacle.
(Then a better question might be: why didn't they just use Go for Flutter? The technical answer could be that Go is more of a systems language like C/C++ and less suitable for UI code. In truth it might just be a common case of Google starting multiple indepent projects that accomplish vaguely the same goals.)
Go focused on trying to solve for particular pain points within a certain class of applications. Those who had those pains were quick to jump on it to solve their problems.
Dart tried to build a better mousetrap. While you might say it succeeded, it wasn't enough to get people away from their older and less fancy, but working, mousetraps.
I find the reason it works is because it has a smaller surface area and the culture is to even enforce formatting (with go fmt). Your brain has an easier time coming back to things and parsing them, even if the language isn't exactly "right".
1) Go is still the only language is not developed by analogy (i.e. let's do X because all other languages have it). It's designed from the first principles, and that's why so many newcomers are buffed about weirdly different take on things they consider "basic" or "common sense". "Less is more" sounds funny for people coming from the feature-bloated languages.
For me, minimalistic feature space was a breath of fresh air. I liked how Go authors see it as a vector space, with features being basis vectors (that's where "orthogonality of features" comes from in the articles about Go). Thus Go is optimized to simplify the search for the optimal path in that vector space which is a proxy for cognitive load while writing code. I'm not sure why it's noy obvious for other languages designers, but seems like "the more features - the better" narrative is rarely questioned. Go holds its stand firmly here.
2) Go tooling got it fair share of praises, and inspired other languages and frameworks to follow the same approach. Rustfmt or single binary `flutter` tool for everything are good examples. But back then in 2013 it was, again, an unusual approach that reflected some amount of thought and design put in it. (As opposed to the zoo of different commands, approaches and tools in many other languages).
3) Go was quite close to hardware – you could play with structures bit packing if you need to. Witnessing how whole companies burn cash to scale servers while using memory and CPU hungry languages (and not raising an eyebrows over that), Go seemed like a perfect choice for anything server and backend related.
4) Appeal to authority is not a logical fallacy when the authority is an actual authority. Designing a programming language requires more than CS course on compilers. Go authors had extremely deep understanding of hardware and software internals (obviously), but also had *decades* of practice in different teams, companies and even epochs. That made me trust their decisions over my initial responses. I still remember how I was mad at gofmt ("Who the hell they think they are to tell me how I want to format my code!"). Needless to say I was struck by how incredibly useful that turned to be at scale.
What was never on my list of Go selling points is that it was originated in Google. Never understood this argument. I have more respect to Apple than to Google, yet I'm not writing Swift just because it's backed by company I respect more.
Clever mnemonic tecnhique which is much easier to use and memorize. Most people can remember "January 2nd 2006" and "15:04:05" easily, and then crafting date/time format strings becomes a toy.
While with more widespread and common "HH/MM/SS" approach, which has bunch of incompatible implementations in different languages, you have to constantly do mental gymnastics remembering if "MM" means minutes or months, and whether "Y" or "yyyy" represents full year.
Format string "D m y", for example, produces:
- 'Tue 05 22' in PHP
- '05/31/22 05 22' in Ruby and Rust
- 'D 40 22' in .Net
- '151 23 2022' in Dart and Swift
I have no idea how such a messy and suboptimal approach to date formatting even makes sense to people. But of course, many people are bashing Go date formatting simply because it's not what they used to in other languages.
It's a really dumb date because it's so easy to just pick a date that was greater than 12 to easily make out that something is a date and not a month. As it is, 01-02 could literally be anything. I much prefer strftime formats to Go's inane date formatting thing. I find it MUCH easier to simply remember "dd-mm-YYYY" (which is about the only format I use almost 99% of the time) than the specific date they're looking for. I don't really care if something is different in other languages. I'm already context switching and it's easy to look this up
Which, would be intuitive and easy to remember if month-day-hour-minute-second-year-timezone was a sane logical ordering.
> Format string "D m y", for example, produces:
> - '05/31/22 05 22' in Ruby and Rust
How are you doing that in Ruby? The standard Ruby DateTime formatting method is DateTime#strftime() which uses approximately (mostly, fixing the locale-dependent options because the method is not locale sensitive) POSIX strftime format strings, which that is not.
Did you mean “%D %m %y”? Then that's right for Ruby/Rust. But that doesn't seem to produce the results you list for other languages (some of which also have a POSIX-ish strftime, though, e.g., it is deprecated in PHP.)
Or that they are used to simple things being kept simple in other languages. Case in point - String enums in Go:
const (
Summer Season = iota
Autumn
Winter
Spring
)
func (s Season) String() string {
switch s {
case Summer:
return "Summer"
case Autumn:
return "Autumn"
case Winter:
return "Winter"
case Spring:
return "Spring"
}
return "Unknown"
}
Same in Java (invalid values would raise an exception):
Obviously Go code shown here doesn't show string enums. It's an integer enum with function that converts integer value to the string representation (by implementing Stringer interface). Which makes total sense (not every int enum needs String conversion).
I assume your Java example has some magic (aka conventions) in how to convert values into string. Without reading Java manuals, how do I know what's the magic's conversion function? With single words it's usually easy, but try two words "LeapYear" or text with non-Unicode chars - how the magic will work then? Go tries to minimize amount of hidden magic. Also, should not Java enums be capitalized?
I mean, sure, Go enums can be improved, and there are few proposals (none of them yet passed, and that's usually for a reason), but this comparison is just incorrect.
> Obviously Go code shown here doesn't show string enums. It's an integer enum with function that converts integer value to the string representation (by implementing Stringer interface). Which makes total sense (not every int enum needs String conversion).
Considering your robust defence of Go, maybe you can demonstrate the simplicity of Go's string enums?
> I assume your Java example has some magic (aka conventions) in how to convert values into string. Without reading Java manuals, how do I know what's the magic's conversion function?
There is no magic - .toString() produces an equivalent string. The point is to keep simple things simple - most of the time, the enum value and its string representation is same and the snippet in my previous post automatically gets us there.
> With single words it's usually easy, but try two words "LeapYear" or text with non-Unicode chars - how the magic will work then? Go tries to minimize amount of hidden magic.
Thanks for acknowledging that it is atleast easy in Java for single words. Words with spaces or unicode (I think thats what you meant when you said non-Unicode) isn't terrible either:
enum Season {
SUMMER("S U M M E R "), AUTUMN("A U T M N "), WINTER("W I N T E R "), SPRING(
"S P R I N G ");
private String value;
private Season(String value) {
this.value = value;
}
public String toString() {
return this.value;
}
}
I had to introduce a variable and couple of one-line methods which isn't super simple but still a win over a switch statement that requires listing out every representation. For shits and giggles, this is how I can enumerate over the enum values in Java:
for (Season s : Season.values()) {
System.out.println(s);
}
Feel free to show how you would do it in Golang with iota magic...
PS: seems like the unicode strings that I pasted didn't carry over to HNs code snippet. The same is available on pastebin: https://pastebin.com/Yw0jyGDE
I think people mean different things by enums. Is it just a set of constants of a given type or a sum type (aka variant type)?
Go doesn't have sum types at all.
`iota` is just a syntax sugar for enumerating integer constants/variables.
But as you're talking about string enums, the Go equivalent would be:
type Season string
const (
Summer Season = "Summer"
Autumn = "Autumn"
Winter = "Winter"
Spring = "Spring"
)
But, again, that's not a variant type, so you can still assign a different value to the variable of the type Season. Which is rarely a problem in practice (there are other ways to validate data rather than by type system constraints).
So just to clarify, many of the use cases for enumerated values do not need string representation. Go has no magical way to translate varibale/const name into the string.
> An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. [0]
> Is it just a set of constants of a given type or a sum type (aka variant type)?
So by above definition, it is a set of predefined constants.
> But, again, that's not a variant type, so you can still assign a different value to the variable of the type Season.
Which kinda defeats the purpose doesn't it?
> Which is rarely a problem in practice (there are other ways to validate data rather than by type system constraints).
I'm not sure I agree that it is a rare problem - if I can't rely on the type system to do a check that something belongs to a set of predefined constants, that is a pretty basic part missing. Of course there would be other ways but being able to lean on the type system would be a pretty reasonable expectation.
> So just to clarify, many of the use cases for enumerated values do not need string representation.
Sure - just like many of the use cases do require string representation. It is not unreasonable to expect that enumerations as defined above should be able handle cases that do and don't require string representation.
> Go has no magical way to translate varibale/const name into the string.
You keep using this word magical when it comes to addressing the limitations of the language. Java isn't doing "magic" when it is able to return a string representation of the enum value - it is part of the language. Credit where credit is due etc.
Have you actually tried it or you just ranting that Go is not Java?
Take `time.Weekday` type, for example from Go stdlib. It's a typical use of kinda enums in Go. [1]
It serves the purpose to effectively use Weekday whenever it's needed – in literals, in tests, in debug output, etc. Internally it's just an int, but for humans it's better to work with named predefined constants. Instead of creating yet another language feature that will automagically (yes, I keep repeating it, because it matters) convert variable names into strings, Weekday type leverages other Go features to achieve it in a more appropriate way, implementing proper string conversion for long and short forms for English and leaving room for proper i18n handling (it's still a named int constant). [2] Having it as a separate named type makes it handy for proper type checking (so you can't pass some integer with incorrect value to the function expecting time.Weekday).
And now you're saying that it's all useless and wrong, because compiler is not enforcing range of values that varaible of this type can have. But I tell you that it's useful and helping code readability enormously even without being a sum type.
And I hope it's clear that when you switch to another language, the worst thing you can do is to complain that it's different from your previous favourite language. You not just switching use another syntax, but you changing the ways to do things and even philosophy. It's like moving to another country - you not just changing a language, you switching to a different culture and economy. You adopt their social norms, follow the rules of that country and pay taxes even if in your country it was all different.
So yeah, in Go there are no sum types aka enums. And you know what, Go is extremely effective at what it was designed to despite of this. And "Go enums" work just fine, until they may be improved in the future when community is in consensus on how implement it, respecting backward-compatibility rule.
> Go is still the only language is not developed by analogy [...]. It's designed from the first principles,
It's really not even close to that
though if it is such an principles-first language at all (maybe it is, certainly not the only one in existence) it's unusual among such language in not being a pure implementation of an easily articulable paradigm.
"is not developed by analogy" is such a strange thing to say. Technology evolves in generations. The mistakes and lessons of one lead to the next. For example, in the sequence of C -> C++ -> Java -> Scala/Kotlin it's very easy to see how in each new iteration previously ugly areas were improved upon.
Started a project in Golang this week. Looked into web frameworks and was underwhelmed. Settled with Echo as it seems to have the only decent documentation. Still no good templating library, will settle with html/template and try to add something else for template inheritance.
(I chose Golang for the best async scheduler and the very fast compile times).
This is where the problem lies. Everyone and their mom thinks it's trivial to do authentication and authorization (as an example), so they keep rewriting things and in many cases full of security bugs, instead of using something created by people with expertise.
Go filled a niche that wasn't served well: network services with performance/capabilities exceeding scripting languages. Back then the other options were mainly Java, JVM-based niche languages, or C++ — each with its own problems and detractors. Server-side switching costs are low: if it can talk HTTP, you can use it.
Dart was meant to be a better JavaScript, but the barrier to entry for a new browser-native language is impossibly high: it needs consensus of all browser vendors plus a decade for all users to upgrade. Dart made a fatal mistake of betting on having a brand new browser VM instead of being a good compile-to-JS language. In the meantime, JS itself has improved (ES5, ES6), and TS has been designed for being a first-class JS compilation target. The "better JS" niche has been filled by JS.
Dart had quite a long history before Flutter even came into the picture. Flutter is the answer to the question of why is Dart somewhat relevant today, but not to the question of why Dart didn't take off in general during its first 5 or so years, despite the fanfare of coming from Google.
Angular is indeed quite popular. Same as go is not the most used programming language in the world, angular may not be the most used frontend framework, but it's in the top tier.
> On the production side, Google was running very large systems. For example, in March 2005, one 1,500-CPU cluster of the Sawzall log analysis system processed 2.8 PB of data.26 In August 2006, Google's 388 Big-table serving clusters comprised 24,500 individual tablet servers, with one group of 8,069 servers.
Neat. I have a custom golang binary (~20k loc) running on a cluster of close to 20k baremetal servers. As a language, it isn't perfect and I have some complaints, but it was definitely the best tool for this job.
No need to overthink it, I think – it fills a niche where there were poor choices before. It's a safe(ish) language offering a reasonably fast runtime, with good tooling, a standard library that covers most common requirements, some clever and clean API design, and which generates native binaries. It's pretty pragmatic in that sense.
I still find it a bit of a frustrating wasted opportunity – the type system in particular just needs a few more steps to make me feel comfortable. But others may feel differently.
> Extending my service is so fast. Just write the the code, compile it in seconds and it mostly works 90% first try.
This basically describes... every popular programming language. How would this be different in f.e. C#? Compile times might be a tad bit faster but that's about it?
No even anymore, for most changes done in C# using web apis (what go does best), you don't even have to recompile the entire code. It's actually faster doing it in C# by just `dotnet watch` and let hot-reload do its thing.
I've only written about 20k lines of Go code, but Rust has somewhat ruined Go for me. It's really hard to pick Go when I know Rust can do the job better and with fewer resources and bugs. I do think Go brought some good things to the industry though.
Coming from years of Scala development, it does stand in my way all the time. It's so verbose and it's capabilities for abstraction are very limited, it's hard to do anything complex quickly without tons of code generation.
I realize having a language with a gentle learning curve that ends at a very low level has its benefits if you want to commoditize software development, and lots of people want just that, but for me it does kill much of the fun. It doesn't seem very suitable for large-ish projects either, at least I haven't seen one that wasn't a mess yet.
Apart from the concurrency benefits, Golang provides actual value like C or C++.
Therefore it got popular without incessant propaganda and a large consultancy ecosystem (unlike Python, which relies on brutal marketing: There are basically two uninteresting syntax posts on the front page every day, just to keep the brand recognition going).
- Backed by a well known Company with a good image (at the time).
- Made by well known experts at the top of their field.
- Most of the risky, complex and powerful stuff is in the runtime.
- The language surface is small, familiar, conservative and consists of mostly orthogonal features.
- Very straightforward to integrate libraries and a good standard library.
- Portability and deployment are primary concerns.
- Came out at just the right time.
- Evolves without breakage.
There are significant differences between those languages, for example the JVM is a much more dynamic runtime. But I think the conservative surface paired with powerful internals is what makes it so attractive for wide adoption. It is the "blue collar" language strategy.
Languages that have more unique value propositions, lean stronger on niche paradigms and give more power to the programmers are scarier from a mainstream business perspective. I think these kind of languages have a firm stand in their respective niches and will continue to grow steadily, but will stay specialized and at the edge, while mainstream languages slowly adopt features that have been proven to work in other ecosystems.
Go is a language that belongs to the mainstream category, like Java, C#, JavaScript, Python etc. They are "Worse is better" languages that trick you into adopting some good stuff unknowingly and they all have a laser focus on pragmatism and growth.