In the program below, newInstance returns two values. The *recorder result is used, in the innermost closure, but unparam reports:
$ go run mvdan.cc/unparam@v0.0.0-20260823230713-2fa3d841b0c8 .
main.go:15:34: main$1 - result 1 (*example.com/unparamrepro.recorder) is never used
exit status 1
// Using module example.com/unparamrepro as module name
package main
import "fmt"
type widget struct{ n int }
type recorder struct{ entries []string }
func run(f func()) { f() }
func main() {
// "result 1 (*example.com/unparamrepro.recorder) is never used"
// Although the doubly-nested closure at the bottom uses it.
newInstance := func() (*widget, *recorder) {
return &widget{n: 1}, &recorder{}
}
// Deleting either one of the two discarding closures makes the warning disappear.
run(func() {
w, _ := newInstance()
if w == nil {
fmt.Println("nil widget")
}
})
run(func() {
w, _ := newInstance()
if w == nil {
fmt.Println("nil widget")
}
})
// Removing one nesting level around the use makes the warning disappear as well.
run(func() {
run(func() {
w, r := newInstance()
if w == nil {
fmt.Println("nil widget")
}
// This is the use that unparam fails to see.
if len(r.entries) != 0 {
fmt.Println("unexpected entries:", r.entries)
}
})
})
}
In the program below,
newInstancereturns two values. The*recorderresult is used, in the innermost closure, but unparam reports: