Hacker News new | ask | show | jobs
by allset_ 723 days ago
> - Files ending with "_unix.go", "_linux.go", "_windows.go" etc. will only be compiled when compiling for the specified platform. The exact list of platform is very hard to find in documentation.

Sure, you won't find it in the Go 101 guides, but it is well documented in the "go build" CLI reference in the official Go docs site. See https://pkg.go.dev/cmd/go#hdr-Build_constraints and https://pkg.go.dev/internal/platform.

2 comments

GP made the point a few lines below.

What if Go adds support for a new OS called "FoOS" and suddenly your files named "my_foos.go" stop being compiled anywhere else?

They should have forbidden using _ in file names except for an allow-list of suffixes

This has in fact come up before, and you may be surprised to learn the approach they take is most reasonable.
I'm the first to argue that Go is "most reasonable" all around.

Even things which are technically wrong and _could_ have been done differently are still reasonable.

First and foremost because sometimes the alternatives would have meant breaking backwards compatibility (or at the very least forcing people to hassle with migrating code with "editions", which are probably better left for more impacting problems than "what if a new OS comes around")

That said, I think it's important to call out design mistakes when one sees them (as long as one engages constructively with them instead of just throwing a random "Go is magic/sucks/etc" without putting things into context, like how do other practical languages fare on all the metrics combined)

Something I have found surprising and tripped over is that the commands are not the same as the language and the Go team generally does not scrutinize changes which break invocation of commands in the same way that they do the language via the Go 1 compatibility guarantee.

I think overall the semantic filename build constraints `_GOOS_GOARCH` as well as `_test` suffixes provide real value in that I immediately know that the file is build constraint guarded, and it aids my ability to read/browse code greatly. If that information were not encoded in the filename, but only in build tags in each file, then it would be a fairly significant hit to my productivity. I can't see any alternative that is not more complex, and I have issue finding that complexity justified.

I think there is a tradeoff here, the Go team knows it, and that in practice the tradeoff is worth it. There are many such things in Go, tradeoffs of purity and theoretical issues for the sake of practicality, and by and large they're okay.

Perhaps I wasn't clear.

I also like the use of the file name "pre-extension" to categorize files.

There was a way to have the cake and eat it too which is: forbid _ inside the file name other than the extensions that have a well known meaning and treating the others as reserved.

To be honest that seems worse. It feels overly restrictive and surprising. What sort of error do I get? Is the file ignored?

Sometimes perfect is the enemy of good.

Also, frustratingly, ”_unix.go" doesn't work IIRC even though "unix" is a built-in build tag, because the ending thing only works with platform names. You need to manually do "//go:build +unix" in the file.