Skip to main content

Go

Constellation supports Go out of the box. Running constellation index automatically detects .go files and extracts structural metadata for functions, methods, structs, interfaces, and the relationships between them — no configuration required.

For richer cross-package analysis, the --enrich flag enables gopls integration, adding interface implementation edges, more precise call hierarchies, and cross-package type resolution.

Quick Start

# Base indexing — auto-detects .go files, no Go toolchain required
constellation index

# Enriched indexing — starts gopls for richer cross-reference and type data
constellation index --enrich

The first time --enrich runs against Go files, Constellation auto-installs gopls into ~/.constellation/lsp-servers/bin/gopls if Go is available on your PATH.

Requirements

RequirementBase indexingWith --enrich
Go toolchain on PATHNot requiredRequired
go.mod (or go.work) in project tree or any ancestor directoryNot requiredRequired

Go toolchain: gopls is installed via go install, so the Go toolchain must be present and on your PATH before running enriched indexing for the first time. Download Go from go.dev/dl.

go.mod: gopls requires a module-aware project. Any go.mod file in the project tree or an ancestor directory satisfies this requirement. If your project does not have a go.mod, run go mod init <module-path> at the project root before using --enrich.

vendor/ directories: Vendored dependencies under vendor/ are excluded from extraction. Only your own code is indexed.

What Gets Extracted

Constellation extracts structural metadata from Go source without transmitting any source text. The following constructs are captured:

Declarations

  • Top-level functions and methods, including receiver types (value vs. pointer)
  • Structs and interfaces with their fields, method sets, and embedded types
  • Type aliases and named types
  • Constants and package-level variables
  • Type parameters and generic constraints

Relationships

  • Import statements, including aliased imports (import log "myapp/logger") and side-effect imports (import _ "net/http/pprof")
  • Function and method call edges with receiver-type resolution
  • IMPLEMENTS edges — interface satisfaction detected both within a single file and across package boundaries (requires --enrich for cross-package)
  • EMBEDS edges — struct embedding that promotes methods to the embedding type

Go-Specific Metadata

  • Goroutine spawn points — go fn() calls are flagged with an isAsync attribute on the call edge
  • Pointer vs. value receiver distinction (goIsPointerReceiver field on method symbols)

Privacy guarantee: Function bodies and string literals are never transmitted. Only structural metadata — signatures, types, and relationships — leaves your environment.

gopls Enrichment

Running constellation index --enrich starts gopls alongside the base extraction pass. gopls provides additional information that the structural parser alone cannot reliably derive:

  • Cross-package IMPLEMENTS edges — gopls resolves which concrete types in your codebase satisfy interfaces defined in imported packages, not just interfaces in the same file or module
  • Richer call hierarchies — more precise inbound and outbound call resolution across package boundaries
  • Hover-derived type information — additional type context for complex expressions and aliased types

Automatic Installation

The first time enriched Go indexing runs, Constellation checks whether gopls is already available. If not, and if the go command is on your PATH, it automatically runs:

GOBIN=~/.constellation/lsp-servers/bin go install golang.org/x/tools/gopls@latest

The binary lands at ~/.constellation/lsp-servers/bin/gopls and is reused on subsequent runs.

Manual Installation

If auto-install fails, or if you prefer to manage gopls yourself, install it manually:

go install golang.org/x/tools/gopls@latest

This installs gopls into your $GOPATH/bin (typically ~/go/bin). Ensure that directory is on your PATH, then re-run constellation index --enrich.

Common Gotchas

"No go.mod found"

gopls requires a module-aware project. Run go mod init <module-path> at the project root to create one, or run Constellation from a subdirectory that has a go.mod in an ancestor directory. Without a go.mod, enrichment will produce zero gopls results — base indexing is unaffected.

go.work workspaces

Multi-module workspaces defined with go.work are currently treated as a collection of standalone modules. Constellation indexes each module independently; cross-module IMPLEMENTS edges via gopls workspaces are on the roadmap.

vendor/ directories

Files under vendor/ are excluded from extraction by design. Vendored dependencies are not your code and do not belong in the knowledge graph.

Build tags

Files with //go:build constraints are indexed unconditionally — Constellation does not evaluate build tags. Build-tag-aware extraction is on the roadmap.

Test files (_test.go)

Test files are indexed alongside production code. A future release will tag them with isTestOnly so queries can filter them out explicitly.

Query Cookbook

The following examples show how your AI assistant can compose code_intel queries to answer Go-specific questions. Each example is a snippet the AI would write and execute in the secure sandbox.

Find all types that implement an interface

// "What implements io.Reader in this codebase?"
const result = await api.searchSymbols({ query: "Reader", filterByKind: ["interface"] });
const reader = result.symbols[0];

// Trace all usages of this interface symbol to find references across the codebase
const usages = await api.traceSymbolUsage({ symbolId: reader.id });
return usages.directUsages;

:::note Roadmap Querying IMPLEMENTS relationships directly (i.e. "which concrete types satisfy this interface") is not yet a single-call operation in the current API. The IMPLEMENTS edges are stored in the graph and enriched by gopls, but a dedicated query for implementers is on the roadmap. :::

Find goroutines spawned by a function

// "What goroutines does this function spawn?"
const search = await api.searchSymbols({ query: "ProcessQueue" });
const calls = await api.getCallGraph({ symbolId: search.symbols[0].id });

return calls.callees?.filter(c => c.isAsync === true);

Find types that embed a struct

// "What files reference the BaseHandler struct?"
const search = await api.searchSymbols({ query: "BaseHandler", filterByKind: ["struct"] });
const usages = await api.traceSymbolUsage({ symbolId: search.symbols[0].id });
return usages.directUsages;

:::note Roadmap Querying EMBEDS relationships directly (i.e. "which types embed this struct") is not yet a single-call operation in the current API. EMBEDS edges are stored in the graph and are on the roadmap for direct querying. :::

Find unused exported functions

// "Are there any exported functions that nothing calls?"
const orphans = await api.findOrphanedCode({ kind: "function" });

// Filter to exported symbols (Go convention: starts with uppercase)
return orphans.orphanedSymbols.filter(s => /^[A-Z]/.test(s.name));