func TypeListFromFieldList(fields ast.FieldList) []Type {
	types := make([]Type, len(fields.List))
	for i, field := range fields.List {
		types[i] = TypeFromTypeExpr(field.Type)
	}
	return types
}
TypeListFromFieldList gets the list of type names from an
ast.FieldList. Names are not returned.
package main
import (
	"fmt"
	"go/ast"
)
type Function struct {
	Name string
	Parameters []Type
	Returns []Type
}
type Type interface {
	ToString() string
}
type ArrayType struct {
	ElementType Type
}
func (ty *ArrayType) ToString() string {
	if ty == nil {
		return ""
	}
	tystr := fmt.Sprintf("[](%s)", ty.ElementType.ToString())
	return tystr
}
type BasicType string
func (ty *BasicType) ToString() string {
	if ty == nil {
		return ""
	}
	return string(*ty)
}
type ChanType struct {
	ElementType Type
}
func (ty *ChanType) ToString() string {
	if ty == nil {
		return ""
	}
	tystr := fmt.Sprintf("chan (%s)", ty.ElementType.ToString())
	return tystr
}
type MapType struct {
	KeyType Type
	ValueType Type
}
func (ty *MapType) ToString() string {
	if ty == nil {
		return ""
	}
	tystr := fmt.Sprintf("map[%s](%s)", ty.KeyType.ToString(), ty.ValueType.ToString())
	return tystr
}
type PointerType struct {
	TargetType Type
}
type QualifiedType struct {
	Package string
	Type Type
}
func (ty *QualifiedType) ToString() string {
	if ty == nil {
		return ""
	}
	tystr := fmt.Sprintf("%s.%s", ty.Package, ty.Type.ToString())
	return tystr
}
func (ty *PointerType) ToString() string {
	if ty == nil {
		return ""
	}
	tystr := fmt.Sprintf("*(%s)", ty.TargetType.ToString())
	return tystr
}
func InterfacesFromAST(theAST ast.Node) map[string][]Function {
	if theAST == nil {
		return nil
	}
	interfaces := make(map[string][]Function)
	ast.Inspect(theAST, func(node ast.Node) bool {
		switch tyspec := node.(type) {
		case *ast.TypeSpec:
			name := tyspec.Name.Name
			switch ifacety := tyspec.Type.(type) {
			case *ast.InterfaceType:
				functions, err := FunctionsFromInterfaceType(*ifacety)
				if err == nil {
					interfaces[name] = functions
				}
			}
			return false
		}
		return true
	})
	return interfaces
}
func FunctionsFromInterfaceType(ifacety ast.InterfaceType) ([]Function, error) {
	var functions []Function
	for _, field := range ifacety.Methods.List {
		if len(field.Names) == 0 {
			continue
		}
		name := field.Names[0].Name
		obj := field.Names[0].Obj
		if obj == nil || obj.Decl == nil {
			continue
		}
		switch fundecl := obj.Decl.(type) {
		case *ast.Field:
			ast.Inspect(fundecl, func(node ast.Node) bool {
				switch funty := node.(type) {
				case *ast.FuncType:
					function := Function{Name: name}
					if funty.Params != nil {
						function.Parameters = TypeListFromFieldList(*funty.Params)
					}
					if funty.Results != nil {
						function.Returns = TypeListFromFieldList(*funty.Results)
					}
					functions = append(functions, function)
					return false
				}
				return true
			})
		}
	}
	return functions, nil
}