func filterExceptions(objs []types.Object, finder func(pos token.Pos) token.Position) []types.Object {
	var out []types.Object
	for _, o := range objs {
		if shouldCheckForUsage(o, finder) {
			out = append(out, o)
		} else {
			debugf("filtering out %v", o)
		}
	}
	return out
}
filterExceptions removes objects from the query target set if they have
special exemptions, like being needed for the sort interface.
package main
import (
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"syscall"
	"github.com/pkg/errors"
	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)
func main() {
	scope := flag.String("scope", "repo root", "scope of search")
	flag.BoolVar(&loggerEnabled, "v", loggerEnabled, "include log output")
	flag.BoolVar(&debugEnabled, "debug", debugEnabled, "include tons of log output (implies -v)")
	flag.Parse()
	args := flag.Args()
	if len(args) != 1 {
		flag.Usage()
		os.Exit(1)
	}
	targetPkg := args[0]
	if *scope == "repo root" {
		root, err := repoRoot(targetPkg)
		if err != nil {
			fatalf("unable to set up scope: %s", err)
		}
		*scope = path.Join(root, "...")
		logf("scope=%v", *scope)
	}
	result, err := unused(&build.Default, targetPkg, []string{*scope})
	if err != nil {
		fatalf(err.Error())
	}
	sort.Slice(result.unusedObjs, func(i, j int) bool {
		return result.unusedObjs[i].Pos() < result.unusedObjs[j].Pos()
	})
	var output []string
	for _, obj := range result.unusedObjs {
		output = append(output, printUnused(result.fset.Position, obj, *scope))
	}
	for _, o := range output {
		fmt.Println(o)
	}
}
type unusedSearchResult struct {
	fset       *token.FileSet
	unusedObjs []types.Object
}
func printUnused(finder func(token.Pos) token.Position, obj types.Object, scope string) string {
	var name string
	switch v := obj.(type) {
	case *types.Func:
		sig, ok := v.Type().(*types.Signature)
		if ok && (sig.Recv() != nil) {
			var recvName string
			recvType, ok := sig.Recv().Type().(*types.Named)
			if ok {
				recvName = recvType.Obj().Name()
			} else {
				recvName = "<unknown>"
			}
			name = fmt.Sprintf("method %s.%s", recvName, obj.Name())
		} else {
			name = fmt.Sprintf("func %s", obj.Name())
		}
	case *types.TypeName:
		name = fmt.Sprintf("type %s", obj.Name())
	case *types.Const:
		name = fmt.Sprintf("const %s", obj.Name())
	case *types.Var:
		name = fmt.Sprintf("var %s", obj.Name())
	default:
		name = obj.Name()
	}
	return fmt.Sprintf("%v: %v is exported but not used anywhere else in %v",
		finder(obj.Pos()).String(), name, scope)
}