- Compared to Java: Ecosystem is way over-engineered. You might get along just fine without writing a bunch of boilerplate and factories and XML configs, but sooner or later you're probably going to pull in some dependency that does and have to deal with a bunch of clunky APIs and other annoyances.
- Python: Possibly the only language that's even worse at dependency management than Go. Installs packages globally. The solution is to create a "virtual environment" which is code for hacking up your PATH.
- Node: I dislike the quirks of Javascript like remembering the difference between == and ===, undefined vs null, etc. I haven't used Typescript which may solve some of those language issues. I also dislike dealing with promises/callbacks for so many operations.
I like Go because:
- I can compile to a single statically-linked binary and cross-compile for other platforms
- I can choose to either vendor dependencies or use go-dep to create a dependency lockfile. I can have multiple GOPATHs with minimal magic.
- The "go" CLI handles pretty much everything I need without an explicit config file like pom.xml or package.json.
- The language lacks features. There is no magic. Way more so than even Python, there is one obvious way to do things and there's even an official style guide, so it's easy to jump into someone else's code and understand exactly what's going on immediately. After working with Scala professionally for a few years, I firmly believe this to be a feature, not a flaw.
- The standard library is incredibly comprehensive. It's completely possible to write a web service without importing a single external dependency. There has been a lot of thought put into library APIs for things like byte Readers/Writers and HTTP handlers, to the point that external libraries still usually stick to these standard interfaces. Contrast that with a language like Python where urllib sucks so everyone uses requests.
In comparison, the entire standard build process for a Go program is:
$ export GOPATH="/path/to/repo" && go get && go build && ./main
No config files with some DSL to learn or handwritten XML, no weird class loader behavior to track down, no tuning memory limits or any of that stuff that is just par for the course in Java.Like C/C++, javac is just a compiler.
It's not a a dependency resolver, a runtime, a formatter, etc.
go is all of those things.
And every time you jump into an existing codebase, you need to scrutinize the docs that are hopefully there to figure out particulars of the build/deploy process.
Which, I'm not sure there's a more durable reputation in all of informatics than Java's reputation for over-engineering things.
There are cleaner Java libraries for most things nowadays, but the culture around the language is also such that, in many companies, it is politically much easier to use another language entirely than it is to use Java but choose a REST framework that doesn't implement JAX-RS.
This might be true but I find it so backwards.
Look up libraries like Spark[1] or Javalin[2] and you get something quite light weight. Or DropWizard[3] if you need something more holistic.
That being said, the moment you need something more involved, say validation, DB access, pre- or post- endpoint call processing (e.g. for authorization), then golang completely falls on its face. There is nothing in golang that compares to Jooq[4] for instance, and because golang doesn't have annotations, you can't do automatic validation or authorization, and you end up having to do everything manually in a verbose and error prone manner.
For static compilation in Java, GraalVM is supposed to be quite good[5]
[1] http://sparkjava.com/ [2] https://javalin.io/ [3] https://www.dropwizard.io/1.3.12/docs/ [4] https://www.jooq.org/ [5] https://quarkus.io/
Also if you compare those codebases to Java (again enterprise) projects of a similar size they seem quite readable instantly..
That hasn't been my experience at an employer. Their devs mainly had Python and NodeJs experience and similar languages (which is what the first version of the code base was written in), and disliked "enterprisey" code. Somehow, the decision to move to golang was made.
Yet, they somehow managed to come up with their own mess, and yes it is mainly because how underpowered golang is. I keep thinking about how much simpler the code base would be if it were written in Java, let alone something like Kotlin.
Everybody has legacy code. Modern Java doesn't mean much if your team is 2 years away from being able to use the modern stuff.
> == vs ===
Just never use ==, and you're done. This is pretty much a defacto standard. It essentially has no legitimate usecase that couldn't be expressed more explicitly with at most 1 extra line, and should just be ignored.
> undefined vs null
I've only very occasionally run into this being an issue. Standard seems to be using the falsey nature of both undefined and null to check for them, !x rather than x === null for example, so that it doesn't really come up much in practice, but anyway...
> TypeScript may solve some of these issues
Yes, it solves both the above :-)
> Dislike dealing with promises / callbacks
Firstly callbacks are hardly seen anywhere any more. And if they are, certainly no more than one level deep, and that's even assuming you don't just promisify the callback function anyway, which is trivial to do.
For Promises - async/await makes dealing with them syntactically much nicer in node. It's pretty much just like synchronous code to read, and in behaviour.
As far as Python, same kind of reasons. Single binary makes deployments easy, static analysis and built in tooling makes life easier, and I just find it more enjoyable, which is completely subjective.
1. Java - did not want to adopt the entire ecosystem. This is very much wanted a banana and got the whole jungle with a gorilla type of story.
2. Python - dynamic. Don't want that. Go's minimal typing is perfect. It's easy to deploy (binaries). It's fast. It can scale well. It's opinionated (love this).
Python and Java both encourage and allow developers to flex creative solutions that are hard to maintain long-term. Sure, seniority helps with that, and being part of a good team; however using Go, you just run into that less due to the conciseness of the language and strong idioms.
Can you please provide some examples? This would be a useful comparison, as Java had way more time to work on the libraries.
Yeah it is tricky, but Java has a good track record here:
In 1.2 they added all-new Collections API. The old API is still there and still works, though it is not used much these days.
Then in 5 or thereabouts Collections API got generics.
Then in 8 or so, Collections API got streams, magical multithreading etc etc.
Lambdas were added to the language and standard libraries, and so on.
I work on Golang stuff at work where we made the switch after the troubles associated with refactoring Python. Recently though, I 'typed' a personal project of mine that was fairly large, and it's become a pleasure to work on.
IDE integrations of mypy warn you as soon as type errors occur. The fact that the type annotations are first-class features of the language and not embedded in comments also makes it great. The compromise of type-safety at the boundaries where you interface with 3rd party APIs that don't provide type annotations (the major ones do) does not get in the way too often contrary to what I expected.
mypy makes Python a pleasure to work with again.
This is my experience as well. I love that I have the option to use Python typed and untyped. For little scripts, fiddles, prototypes, etc. it's often convenient to omit type annotations. For solid software that runs in production it's nice to have them.
Another thing that I'm excited about is nuitka [0], a Python to C compiler that allows you to create binaries from Python code. It cut start-up time of a command line tool that I compiled with in half.