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 purego or manual dlopen-style loading can defer dependency checks to runtime, improving cross-compilation at the cost of complexity.
  • Some advocate calling journalctl with JSON/export output instead of linking libsystemd; 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.