They really are. It drives me nuts because you don't need Go for static binaries, but in practice almost all Go programs are static and almost all non-Go programs are dynamic. I've even tried to build static binaries out of ex. C and it's a huge pain because nothing expects you to do that so you have to fight your libraries since your distro probably didn't ship the static .a files to link in, and apparently you can't just reuse the normal versions. So, basically network effects mean that Go=static, not-Go=not-static, which is sad.
Simplest explanation I can think of:
Static binaries have no dependencies. They should just run and not bark about missing (shared/dynamic) libraries, nor require you to install them.
Of course, even static binaries rely on some basic level of compatibility; typically system-level things that don't change much.
Dynamically-linked binaries have the potential to create a massive dependency graph that can hard or even impossible (for a given o/s installation) to traverse.
Which makes sense for large software systems, but for small tools that you might want to carry around on a flash drive or that you need to always work across multiple machines without having a vm, static binaries make sense.
I'm a big fan of Go's static binaries, but I'm sorry, the last point doesn't make much sense to me. The dependency graph is going to be the same whether or not you include everything in your binary. It just so happens that the Go ecosystem hasn't adopted node's cancerous everything-is-a-dependecy pattern (at least yet). If it did, the dependency graph would be equally horrendous; the only difference is that the dependencies are included in the binary.
* single binary that you can scp (or use transfer.sh haha) into the production machine and run; no runtime environments, package installation etc.
* two different applications can depend on different versions of a library without any intermediate package manager or virtual environment
* guaranteed execution: related to the first point, but I see enough merit in this to make it a separate point
Cons:
* If there's a security issue in a commonly used library (database/sql, for example), you'll need to patch every application that uses it. With dynamic dependencies, you just patch the library.
For dynamic version, you can have different dynamic libraries for different OS'es or optimized for different CPU's, you can share library between different applications saving network/disk/RAM/CPU cache, you can update lib when application vendor no longer exists, you can have different licenses for libraries and application, etc. Just read historic books for details about problems with static binaries.
For illustrative purposes, you could think of a static binary kind of like a Docker container. Like a container, within the binary is all of its dependencies, meaning that you are free to install conflicting libraries on the system.
If you use dynamically linked binaries, you rely on the system to have the version of the library you need, and hope that your reliance on those libraries does not break other applications which may rely on different versions of those libs.
Static == everything you need bundled up
Dynamic == relies on libraries present on the host to provide aspects of functionality