Open-source project
mvdan/unparam avatar
mvdan/unparam

unparam finds Go parameters that are never read

Find unused parameters in Go

572 stars32 forksGoBSD-3-Clause

At a glance

What is it?
unparam is a Go linter that reports unused function parameters and results, plus parameters that always receive the same value and results that are never used, while ignoring a list of cases that commonly produce false positives. It is a single-binary tool built on the golang.org/x/tools analysis framework.
Who is it for?
Adopt unparam if your Go codebase has accumulated function signatures that carry parameters nobody reads, since it finds both unused parameters and always-same values, and the ignored cases keep the output small enough to act on. Skip it if your project relies on interface satisfaction, build-tag variants or `go:linkname`, since those are exactly the situations it deliberately stays quiet about.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A linter for a mistake Go's compiler will not catch

unparam reports unused function parameters and results in your code. The problem it addresses is specific to Go's ergonomics: it is easy to leave a parameter in a function signature after the implementation stopped needing it, and the compiler says nothing, because the signature is still valid. The tool is a linter rather than a compiler plugin, and the installation is a single go install line.

bash
	go install mvdan.cc/unparam@latest

The module is `mvdan.cc/unparam` and it is BSD-3-Clause licensed. The dependency list in the manifest tells you how it is built. `golang.org/x/tools` at 0.52.0 is the analysis framework that does the type checking and drives the per-function inspection, and `github.com/rogpeppe/go-internal` is used for the test scripts that exercise the tool. The repository layout is small and standard for an x/tools style analyser, with `main.go` at the root, a `check/` directory holding the analysis logic, `main_test.go`, and a `testdata/` directory of Go source fixtures. That fixture directory is the interesting part for anyone who wants to understand the tool's behaviour, because it is where the cases the tool must not flag are pinned down as expected output.

The ignored cases are the real specification

The README spends most of its length on what unparam does not report, and that list is the substance of the tool. To minimise false positives it ignores exported functions by default, with `-exported` available to change that. It ignores unnamed and blank parameters, the `_` and `_foo` forms, which are the idiomatic way to say a parameter is deliberately unused. It ignores funcs that may satisfy an interface, since an interface method's parameters are dictated by the interface. It ignores funcs that may satisfy a function signature. It ignores funcs that are stubs, meaning empty, only error, or immediately returning. It ignores funcs that have multiple implementations via build tags, where a signature shared across build-tag variants is used differently in each. And it ignores funcs with a `go:linkname` directive. Every one of those is a case where an unused parameter is the only correct way to write the code, and a linter that flagged them would be turned off within a day.

Beyond the unused parameter, three constant checks

The tool reports three things that are all variations on the same theme, and the extra two are where the value is. It reports results that always return the same value. It reports parameters that always receive the same value. And it reports results that are never used. A function whose result is always nil is a function whose result should probably not exist, and a parameter that every caller passes the same value for is a parameter that should be a constant or removed. These are the checks that find dead API surface rather than dead variables. The README is careful about a limit here: in the last two cases, a minimum number of calls is required to ensure the warnings are useful. That constraint is not incidental. A parameter that always receives the same value across the only call site in the codebase tells you nothing about whether it is genuinely constant, and the same applies to a result whose only caller happens to ignore it. The threshold is what keeps a check that looks like a constant-value detector from turning into a false-positive machine.

Precision is the goal, and the tool says so

The README states plainly that false positives can still occur by design, and that the aim of the tool is to be as precise as possible, with a request to file a bug if you find mistakes. That is a specific and unusual thing for a linter to say, and it tells you what the author optimised for. A linter that reports every technically unused parameter in a codebase with interface-heavy design will produce a wall of output that nobody reads, and then it is uninstalled. Precision here means fewer findings, not more. The corollary is that unparam is a tool for a codebase where someone is willing to act on a small number of findings, not a sweep that finds everything. If you want to find every unused parameter including exported ones and interface methods, `-exported` opens the floodgates and you should expect the results to be read differently, as candidates rather than as defects. The project is sponsored through GitHub Sponsors, with monthly tiers offering things like a logo on the README, prioritised issues or direct support in your chat app, and one-time tiers covering a call about a project or a Go consulting or mentorship session, which tells you the author maintains a number of related Go tools.

Where it is the wrong tool

There are clear boundaries, and they are all the mirror image of the ignore list. If your code is built around interfaces with many implementations, the checks that matter most to you are exactly the ones the tool suppresses, because a parameter that is unused in one implementation may be used in another. Code assembled from build-tag variants hits the same problem, and a function whose parameters are dictated by a `go:linkname` target cannot be changed without breaking the link. Stub functions, which is what a codebase full of not-yet-implemented methods looks like, will be skipped too, which means a codebase early in its life will get few findings. The tool also does not address a different class of dead weight, namely a function that is called but whose result is never inspected by anyone, since that is a whole-program reachability question rather than a per-function signature question, and unparam is built on the x/tools analysis framework, which works per package with limited cross-package reasoning. If your goal is to find unreachable code rather than unused parameters, this is the wrong instrument.

Editorial conclusion

Adopt unparam if your Go codebase has accumulated function signatures that carry parameters nobody reads, since it finds both unused parameters and always-same values, and the ignored cases keep the output small enough to act on. Skip it if your project relies on interface satisfaction, build-tag variants or `go:linkname`, since those are exactly the situations it deliberately stays quiet about. Before you act on the warnings, read the note that a minimum number of calls is required for the constant-value and unused-result checks, because a function called once will not be flagged for them.

Frequently asked questions

What does unparam report in Go code?

Unused function parameters and unused results, plus results that always return the same value, parameters that always receive the same value, and results that are never used. The last two checks require a minimum number of calls for the warnings to be useful.

How do I install unparam?

With `go install mvdan.cc/unparam@latest`. The module is `mvdan.cc/unparam` and it is BSD-3-Clause licensed, built on the `golang.org/x/tools` analysis framework.

Which functions does unparam ignore to avoid false positives?

Exported functions unless `-exported` is given, unnamed and blank parameters, funcs that may satisfy an interface or a function signature, stub funcs, funcs with multiple implementations via build tags, and funcs with a `go:linkname` directive.

Does unparam find unreachable functions?

No. It works per function through the x/tools analysis framework, so it reports unused parameters and results rather than functions that are never called anywhere in the program. That is a different question and a different kind of tool.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. mvdan/unparam on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mvdan-unparam.svg)](https://hysenlabs.com/projects/mvdan-unparam)

Was this useful?