Find dead code in Golang monorepo

Try running go build -gcflags -live. This passes the -live flag to the compiler (go tool compile), instructing it to output debugging messages about liveness analysis. Unfortunately, it only prints when it's found live code, not dead code, but you could in theory look to see what doesn't show up in the output.

Here's an example from compiling the following program stored in dead.go:

package main

import "fmt"

func main() {
    if true {
        fmt.Println(true)
    } else {
        fmt.Println(false)
    }
}

Output of go build -gcflags -live:

# _/tmp/dead
./dead.go:7: live at call to convT2E: autotmp_5
./dead.go:7: live at call to Println: autotmp_5

If I'm reading this correctly, the second line states that the implicit call to convT2E (which converts non-interface types to interface types, since fmt.Println takes arguments of type interface{}) is live, and the third line states that the call to fmt.Println is live. Note that it doesn't say that the fmt.Println(false) call is live, so we can deduce that it must be dead.

I know that's not a perfect answer, but I hope it helps.


UPD 2020: The unused tool has been incorporated into staticcheck. Unfortunately, v0.0.1-2020.1.4 will probably be the last to support this feature. Dominik explains that it is because the check consumes a lot of resources and is hard to get right.

To get that version:

env GO111MODULE=on go get honnef.co/go/tools/cmd/[email protected]

To use it:

$ staticcheck --unused.whole-program=true -- ./...
./internal/pkg/a.go:5:6: type A is unused (U1001)

Original answer below.


Dominik Honnef's unused tool might be what you're looking for:

Optionally via the -exported flag, unused can analyse all arguments as a single program and report unused exported identifiers. This can be useful for checking "internal" packages, or large software projects that do not export an API to the public, but use exported methods between components.

Tags:

Refactoring

Go