I'm writing a command line application where a user specifies 1) a directory containing Go files, 2) the name of a variable that should be a http.Handler, e.g.
go run cli.go /path/to/a/go/library MyCustomHandler
I'm trying to
- parse the files
- find the variable with the given name
- verify that it's a
http.Handler
I can do the first two no problem - I call parser.ParseDir, then get the package I want as an *ast.Package, then loop over it like this:
func findHttpHandler(pkg *ast.Package, handlerName string) (*ast.FuncDecl, error) {
for _, file := range pkg.Files {
for _, decl := range file.Decls {
gd, ok := decl.(*ast.GenDecl)
if !ok || gd.Tok != token.VAR {
continue
}
if len(gd.Specs) != 1 {
continue
}
spec0 := gd.Specs[0]
vs, ok := spec0.(*ast.ValueSpec)
if !ok {
continue
}
if len(vs.Names) != 1 {
continue
}
ident := vs.Names[0]
if ident.Name != handlerName {
continue
}
// ...
}
}
}
The problem is at this point the ValueSpec.Type is nil, and there doesn't appear to be any way to figure out whether this is a http.Handler or not.
The go/types package has more tools for checking types, but it also looks like you need to do a lot more setup work to get this, essentially parsing and type checking the whole program. Am I going to need to go down this path, or is there an easier way, just using the ast package, or using go build somehow?