unusedfunc

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: BSD-3-Clause

README

unusedfunc

CI codecov Go Report Card

A Go linter that identifies unused functions and methods with precise rules:

  • Unexported functions/methods: Report if not used anywhere
  • Exported functions/methods: Report if unused AND within /internal packages
  • Strict mode: Report ALL unused exported functions (use when packages aren't imported externally)

Quick Start

go install github.com/715d/unusedfunc/cmd/unusedfunc@latest
unusedfunc ./...

First run? You'll likely see reports for:

  • Unexported helper functions that are no longer called
  • Exported functions in /internal packages that aren't used internally

See Handling False Positives if you encounter reflection-based code.

Key Feature: Internal Package Enforcement

Go's /internal package convention is a compiler-enforced boundary, not a suggestion. unusedfunc enforces it at the function level. Exported functions in /internal packages are treated as implementation details, not public API.

Example:

// pkg/utils/helpers.go
package utils

func PublicHelper() {} // NOT reported (exported in public package - may be used externally)
func privateHelper() {} // REPORTED if unused (unexported)

// internal/utils/helpers.go
package utils

func PublicHelper() {} // REPORTED if unused (exported but in /internal - must be used internally)
func privateHelper() {} // REPORTED if unused (unexported)

This makes unusedfunc valuable for projects that use /internal packages to organize implementation details while allowing cross-package access within the module.

When to Use This Tool

Use unusedfunc if:

  • Your project follows Go's /internal package convention
  • You want to ensure exported functions in internal packages are actually used
  • You need accurate analysis with reasonable performance
  • You want a dedicated tool for unused code detection without broader static analysis overhead

Installation

go install github.com/715d/unusedfunc/cmd/unusedfunc@latest

Other options: Binary releases | Nix | From source

Usage

# Analyze current module
unusedfunc

# Analyze specific packages
unusedfunc ./pkg/...

# Verbose mode: adds statistics and debug logging to stderr
unusedfunc -v ./...

# JSON output (verbose adds 'stats' field to JSON structure)
unusedfunc -json -v ./...

# Strict mode: report ALL unused exported functions (not just /internal)
unusedfunc --strict ./...

# Include generated files in analysis
unusedfunc --skip-generated=false ./...

FAQ

Why is my exported function being reported?

If you see reports for exported functions, check if they're in an /internal package. Go's /internal convention means these functions are not public API — they're only accessible within your module. If they're unused internally, they should be removed or made unexported.

Not in /internal? Exported functions in public packages are never reported in normal mode, as they may be used by external code. Use --strict mode if you're certain your packages aren't imported externally.

When should I use --strict mode?

Use --strict mode when:

  • You're working on an application (not a library) where packages aren't imported externally
  • You want to find unused exported functions across your entire codebase
  • You're certain no external code imports your public packages

Example scenario: You have a web application where all packages are internal to the project. In strict mode, unusedfunc will report ALL unused exported functions, helping you clean up dead code that normal mode would skip.

Warning: Don't use --strict on libraries or modules that external code might import. It will report all unused exports as false positives.

How does this compare to staticcheck's U1000?
Feature unusedfunc unusedfunc --strict staticcheck U1000
Architecture SSA-based analysis with RTA algorithm SSA-based analysis with RTA algorithm AST-based analysis
Exported Functions Reports unused exports in /internal packages Reports ALL unused exports Never reports unused exports
Use Case Libraries + apps following /internal convention Applications with no external imports General-purpose static analysis
Performance Whole-program analysis (scales with codebase) Whole-program analysis (scales with codebase) File-level analysis (consistent overhead)
Philosophy Opinionated: enforces /internal package conventions Aggressive: treats all exports as potentially unused Conservative: avoids false positives
Suppression //nolint:unusedfunc or //lint:ignore unusedfunc //nolint:unusedfunc or //lint:ignore unusedfunc //lint:ignore U1000 <reason>

When to use unusedfunc:

  • Your codebase uses /internal packages to organize implementation details
  • You want to enforce that internal exports are actually used
  • You need precise call graph analysis for interface/generic code

When to use staticcheck:

  • You want comprehensive static analysis beyond just unused functions
  • You need maximum precision across all code quality checks
  • Your codebase doesn't follow the /internal convention
  • You prefer a battle-tested, widely-adopted tool suite
Why isn't this a golangci-lint plugin?

unusedfunc requires whole-program SSA analysis to build accurate call graphs across your entire codebase. This architectural choice enables precise detection of unused exports in /internal packages, but requires different resource constraints than golangci-lint's file-level analyzers.

Run it separately: Add unusedfunc as a dedicated CI step alongside golangci-lint, similar to how you'd run benchmarks or integration tests.

Handling False Positives

Use suppression comments for code called via reflection or templates:

//nolint:unusedfunc
func CalledViaReflection() {}

//lint:ignore unusedfunc Called in template.gotmpl:15
func (t *TemplateContext) Export() string {
    return t.data
}

Common patterns requiring suppression:

  • Methods called via reflect.MethodByName("MethodName")
  • Template method calls (.tmpl, .gotmpl, .html files)
  • Methods discovered by test frameworks
  • Protobuf-generated code

Generated code is skipped by default. Use --skip-generated=false to analyze everything.

Full reference: docs/reference/known-limitations.md — reflection patterns, template limitations, workarounds, and examples.

How It Works

unusedfunc uses SSA (Static Single Assignment) analysis to build a complete call graph of your codebase, then traces reachability from entry points (main, init, tests, exported functions).

Why SSA? Unlike AST-based tools, SSA analysis can accurately track:

  • Interface method calls (which concrete type implements the interface?)
  • Generic function instantiations (which type parameters are used?)
  • Function values passed as arguments

This precision is why unusedfunc can confidently report unused exports in /internal packages.

Technical details: Architecture docs | RTA algorithm

Contributing

Contributions are welcome! Before submitting changes, please run make test && make lint and review our test cases in testdata/.

For detailed guidance on development setup, code standards, and release process, please see our contributing guide.

Directories

Path Synopsis
cmd
unusedfunc command
Package main implements the CLI driver for the unusedfunc linter.
Package main implements the CLI driver for the unusedfunc linter.
internal
analysis
Package analysis provides function metadata and classification for unused function detection.
Package analysis provides function metadata and classification for unused function detection.
harness
Package harness provides test harness infrastructure for validating the analyzer against real-world codebases.
Package harness provides test harness infrastructure for validating the analyzer against real-world codebases.
rta
Package rta provides Rapid Type Analysis (RTA) for Go, a fast.
Package rta provides Rapid Type Analysis (RTA) for Go, a fast.
pkg
assembly
Package assembly provides functionality for scanning and analyzing assembly files.
Package assembly provides functionality for scanning and analyzing assembly files.
runtime
Package runtime provides functionality for detecting and handling.
Package runtime provides functionality for detecting and handling.
ssa
Package ssa implements SSA-based precision analysis for method usage.
Package ssa implements SSA-based precision analysis for method usage.
suppress
Package suppress implements comment-based suppression of linter findings.
Package suppress implements comment-based suppression of linter findings.
unusedfunc
Package unusedfunc provides unused function/method analysis.
Package unusedfunc provides unused function/method analysis.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL