Inspect Go Binaries with go version Without Guessing
You will finish with a repeatable way to identify the Go toolchain behind an executable, inspect embedded build settings, and scan a directory without mistaking an ordinary file for a Go binary. The examples use the installed command on this machine, Go 1.26.1 for Linux amd64. The Debian go-version(1) manpage is older than that binary, so the version check in this guide is part of the workflow.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and read access to the files you want to inspect. All commands below are ordinary, unprivileged reads. Do not use sudo to make an unreadable or non-existent executable look like a Go binary. Fix the path or permissions with the owner of the file instead.
1. Check which go command you are running
Start with the command on your PATH. This avoids comparing output from one installation with binaries built by another:
$ command -v go
/home/linuxbrew/.linuxbrew/bin/go
$ go version
go version go1.26.1 linux/amd64
Your path and version may differ. The useful facts are the selected executable, the Go release, the operating system and the architecture. Check the package manager separately if you need to audit how that toolchain arrived on the host:
$ dpkg-query -S "$(command -v go)"
dpkg-query: no path found matching pattern ...
That last result is not an error in go version. It means this particular binary is not owned by a Debian package. A package query can also identify a distribution-managed installation.
Checkpoint
Record the exact go version line before investigating a build. If it changes between shells, inspect PATH and any version-manager configuration before drawing conclusions.
2. Identify one executable
Pass the file path to go version. It reads the binary and prints the Go version used to build it:
$ go version /path/to/application
/path/to/application: go1.24.6
The result describes the file, not necessarily the go command currently installed. That distinction matters when a service was built in CI or copied from another host. Keep the path in the output: it makes logs useful when several binaries are checked together.
A non-zero result or an error normally means the path could not be read, the file is not a recognised Go binary, or the file is damaged. Check it without changing anything:
$ ls -l /path/to/application
$ file /path/to/application
$ test -r /path/to/application && echo readable
Do not infer the language from a filename or from the presence of a go.mod file beside it. go version examines the executable itself.
3. Read embedded module and build information
Add -m when you need more than the toolchain release. The output includes the embedded module path, build mode, compiler and selected build settings when that information is present:
$ go version -m /path/to/application
/path/to/application: go1.24.6
path example.invalid/warehouse
mod example.invalid/warehouse (devel)
build -buildmode=exe
build -compiler=gc
build GOARCH=amd64
build GOOS=linux
Each metadata line after the version line is indented by a tab. Output varies with the Go release and with how the binary was built. A stripped or unusually old binary may provide less information, and a binary without embedded module information may show only its toolchain line.
Use this command when checking a deployment artefact against a source release. It does not prove that the source tree is available, that dependencies are safe, or that the executable is suitable for production. It reports metadata embedded at build time.
4. Scan a directory recursively
If you have several artefacts, pass a directory rather than writing a loop. The command walks that directory recursively and reports recognised Go binaries:
$ go version /srv/releases
/srv/releases/api: go1.24.6
/srv/releases/tools/report: go1.23.4
Unrecognised files are silent by default. This is useful for a release tree containing archives, checksums and documentation. Add -v when you need to see those files too:
$ go version -v /srv/releases
/srv/releases/api: go1.24.6
/srv/releases/README.txt: unrecognized file
/srv/releases/tools/report: go1.23.4
The exact diagnostic wording can vary by Go release. Treat the recognised binary lines as the result and the unrecognised entries as a prompt to check file selection, not as evidence that the directory scan failed.
For a machine-readable inventory, the installed Go 1.26.1 command also accepts -json:
$ go version -json /path/to/application
{
"Path": "example.invalid/warehouse",
"Main": {"Path": "example.invalid/warehouse", "Version": "(devel)"},
"GoVersion": "go1.24.6",
"Settings": [{"Key": "GOOS", "Value": "linux"}]
}
Use -json only after checking the local help. It is not listed in the installed Debian manpage used for this guide, but it is present in the Go 1.26.1 binary. On this command, -json requires -m according to go help version; an older toolchain may reject the option entirely.
5. Keep inspection separate from changes
go version does not rebuild, sign, modify or restart anything. It is therefore safe to use in a deployment check, but it cannot repair a mismatch. If the reported Go release is unexpected, preserve the original artefact and investigate the build pipeline, image layer or copy operation. Do not overwrite the binary merely to make its version agree with a ticket.
When scripting a check, capture both output and the exit status. A successful status means the command completed its inspection; it does not certify that the programme is trusted or that its embedded metadata is complete:
$ go version -m /path/to/application > /tmp/application-go-version.txt
$ status=$?
$ printf 'inspection status: %s\n' "$status"
inspection status: 0
The temporary report is ordinary text and can be removed after review. Do not redirect output over an existing audit record unless that replacement is deliberate and recoverable.
Done means
- You confirmed which
goexecutable and Go release your shell uses. - You checked the target executable itself, rather than trusting its filename or nearby source files.
- You used
-mfor embedded module and build settings when the binary contains them. - You used a recursive directory scan and added
-vonly when unrecognised files mattered. - You treated
-jsonas Go 1.26.1-specific here and checked local help before scripting it. - You inspected files without changing, restarting or replacing any programme.