Go is portable, until it isn't
Scope of Go Portability
- Pure Go code compiled statically is generally easy to cross-compile and deploy; you still need one binary per CPU/OS, but you don’t need target runtimes.
- Once you use CGO or rely on system libraries (libsystemd, libc, libpq, OpenSSL, etc.), portability problems appear that are not Go‑specific and exist in Rust/C as well.
- Some point out Go on Linux was never fully “just drop on any distro” portable, because robust DNS/user resolution often goes through libc/PAM; pure-Go fallbacks work only for simpler setups.
Cross-Compilation vs Dynamic Linking
- Cross-compiling pure Go is straightforward; cross-compiling with dynamic libraries is harder because you need target shared libs and a proper sysroot.
- Several people successfully build static Go+CGO binaries (including cross-arch) using flags like
-ldflags '-extldflags "-static"', often with musl (e.g., Alpine) because glibc static linking is fragile. - Others stress this is a tooling/packaging problem, not a language one; traditional cross-compilers were worse, and Go/Zig improved things but don’t remove the need for correct target dependencies.
Alternatives to CGO and System Libraries
- For many common dependencies there are pure-Go options: SQLite drivers, Postgres drivers (
lib/pq,pgx), journald writers/parsers, etc., which restore Go’s “single static binary” story. - Libraries like
puregoor manualdlopen-style loading can defer dependency checks to runtime, improving cross-compilation at the cost of complexity. - Some advocate calling
journalctlwith JSON/export output instead of linkinglibsystemd; others argue shelling out is brittle and introduces its own failure modes.
Critique of the Article and Design Choices
- Multiple commenters say the core issue is choosing a Linux‑specific C API (systemd journal) and binary log format, then expecting transparent portability to macOS/Alpine.
- The title is widely viewed as misleading or clickbait: the problems would arise in “Go, Rust, Zig, whatever” once you tie into non‑portable C APIs.
- Others counter that Go’s broader portability story (e.g., around libc types and build tags) is weaker than it markets, and this incident is another symptom.
- Some suggest that writing or adopting a pure-Go journal parser—even if imperfect—might have been simpler long term than fighting CGO, toolchains, and distro differences.