Live data from Hacker News

Go is portable, until it isn't

simpleobservability.com

41–50 of 138 posts

Re: Go is portable, until it isn't

#42
post #2

This seems to imply that Go's binaries are otherwise compatible with multiple platforms like amd64 and arm64, other than the issue with linking dynamic libraries. I suspect that's not true either even if it might be technically possible to achieve it through some trickery (and why not risc-v, and other architectures too?).

For a single binary that will actually run across both architectures, see https://cosmo.zip/>.

Original discussion: https://news.ycombinator.com/item?id=24256883>.

Re: Go is portable, until it isn't

#45
post #19

You hit this real quick when trying to build container images from the scratch. Theoretically you can drop a Go binary into a blank rootfs and it will run. This works most of the time, but anything that depends on Go's Postgres client requires libpq which requires libc. Queue EFILE runtime errors after running the container.

> anything that depends on Go's Postgres client requires libpq which requires libc Try https://github.com/lib/pq

I've also seen https://github.com/jackc/pgx used in many projects

Re: Go is portable, until it isn't

#47
post #24
post #22

Earlier quoted context omitted.

In general, cross compilers can do dynamic linking.

In my experience, the cross-compiler will refuse to link against shared libraries that "don't exist", which they usually don't in a cross compiler setup (e.g. cross compiling an aarch64 application that uses SDL on a ppc64le host with ppc64le SDL libraries) The usual workaround, I think, is to use dlopen/dlsym from within the program. This is how the Nim language handles libraries in the general case: at compile time…

You just need a compiler & linker that understand the target + image format, and a sysroot for the target. I've cross compiled from Linux x86 clang/lld to macOS arm64, all it took was the target SDK & a couple of env vars.

Clang knows C, lld knows macho, and the SDK knows the target libraries.

Re: Go is portable, until it isn't

#48
post #19

You hit this real quick when trying to build container images from the scratch. Theoretically you can drop a Go binary into a blank rootfs and it will run. This works most of the time, but anything that depends on Go's Postgres client requires libpq which requires libc. Queue EFILE runtime errors after running the container.

> anything that depends on Go's Postgres client requires libpq which requires libc Try https://github.com/lib/pq

> For users that require new features or reliable resolution of reported bugs, we recommend using pgx which is under active development.

Re: Go is portable, until it isn't

#49
post #9

I ran into this issue when porting term.everything[0] from typescript to go. I had some c library dependencies that I did need to link, so I had to use cgo. My solution was to do the build process on alpine linux[1] and use static linking[2]. This way it statically links musl libc, which is much friendlier with static linking than glibc. Now, I have a static binary that runs in alpine, Debian, and even bare container…

Huh. Does term.everything just work, or are there some gotchas? This seems like it could be supremely useful!

Re: Go is portable, until it isn't

#50

Once you use CGO, portability is gone. Your binary is no longer staticly compiled. This can happen subtley without you knowing it. If you use a function in the standard library that happens to call into a CGO function, you are no longer static. This happens with things like os.UserHomeDir or some networking things like DNS lookups. You can "force" go to do static compiling by disabling CGO, but that means you can't u…

> Which may not work if you require it for certain things like sqlite.

there is cgo-less sqlite implementation https://github.com/glebarez/go-sqlite it seems to not be maintained much tho

Post reply on HN