go list -json for Package Metadata
go list -json for Package Metadata
Thesis
go list -json is the stable way to ask the Go toolchain what it knows about a package or module: import path, source files, imports, and more. Scripts should parse JSON, not scrape go list text tables.
Mental model
go list -json <pattern>
→ one JSON object per package (stream)
go list -json -m
→ module object for the main module
Useful fields: ImportPath, Dir, GoFiles, Imports, Deps, Module, TestGoFiles.
Worked example
Verified with Go 1.27.2.
go list -json encoding/jsonExcerpt from this box:
ImportPath: encoding/json
Name: json
Dir: /usr/local/go/src/encoding/json
Doc: Package json implements encoding and decoding of JSON as defined in RFC 7159.
Root: /usr/local/go
Module: None
GoFiles: ['v2_decode.go', 'v2_encode.go', 'v2_indent.go', 'v2_inject.go', 'v2_options.go', 'v2_scanner.go', 'v2_stream.go']
Imports: ['bytes', 'cmp', 'encoding', 'encoding/json/internal', 'encoding/json/internal/jsonflags', 'encoding/json/internal/jsonopts', 'encoding/json/internal/jsonwire', 'encoding/json/jsontext', '...(15 total)']
Deps: ['bytes', 'cmp', 'encoding', 'encoding/base32', 'encoding/base64', 'encoding/binary', 'encoding/hex', 'encoding/json/internal', '...(73 total)']
A tiny consumer:
/* listmeta.go */
package main
import (
"encoding/json"
"fmt"
"os/exec"
)
func main() {
out, err := exec.Command("go", "list", "-json", "fmt").Output()
if err != nil {
panic(err)
}
var p struct {
ImportPath string
Name string
Dir string
GoFiles []string
}
if err := json.Unmarshal(out, &p); err != nil {
panic(err)
}
fmt.Printf("%s (%s) files=%d\n", p.ImportPath, p.Name, len(p.GoFiles))
}go run listmeta.goSample run:
Path=command-line-arguments
ImportPath=fmt Name=fmt Dir=/usr/local/go/src/fmt
GoFiles sample=[doc.go errors.go format.go print.go scan.go]
Trap
Assuming one object. go list -json ./... emits NDJSON (one object per line/package). json.Decoder in a loop, not a single Unmarshal into a slice.
Boring rule
For tooling, prefer go list -json (and -m / -deps as needed) over parsing build IDs or directory layouts by hand. Pin the fields you read; ignore unknown ones for forward compatibility.
Try this
go list -json -deps fmtand count uniqueImportPaths.- Compare
GoFilesvsTestGoFilesfor one of your packages. - Use
-f '{{.ImportPath}} {{.Dir}}'only for quick human views — keep JSON for scripts.
Sources
go help list- Go 1.27 toolchain docs on module-aware
go list