func ReadSourceFiles(p string, recursive ...bool) (string, error) {
	typeDefs := []string{}
	abs, err := filepath.Abs(p)
	if err != nil {
		return "", err
	}
	var readFunc = func(dirPath string, info os.FileInfo, err error) error {
		if info.IsDir() {
			return nil
		}
		switch ext := strings.ToLower(filepath.Ext(info.Name())); ext {
		case ".gql", ".graphql":
			data, err := ioutil.ReadFile(filepath.Join(dirPath, info.Name()))
			if err != nil {
				return err
			}
			typeDefs = append(typeDefs, string(data))
			return nil
		default:
			return nil
		}
	}
	if len(recursive) > 0 && recursive[0] {
		if err := filepath.Walk(abs, readFunc); err != nil {
			return "", err
		}
	} else {
		files, err := ioutil.ReadDir(abs)
		if err != nil {
			return "", err
		}
		for _, file := range files {
			if err := readFunc(abs, file, nil); err != nil {
				return "", err
			}
		}
	}
	result := strings.Join(typeDefs, "\n")
	return result, err
}
ReadSourceFiles reads all source files from a specified path
package tools
import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"github.com/graphql-go/graphql"
	"github.com/graphql-go/graphql/language/ast"
	"github.com/graphql-go/graphql/language/kinds"
)
func (c *registry) getFieldResolveFn(kind, typeName, fieldName string) graphql.FieldResolveFn {
	if r := c.getResolver(typeName); r != nil && kind == r.getKind() {
		switch kind {
		case kinds.ObjectDefinition:
			if fn, ok := r.(*ObjectResolver).Fields[fieldName]; ok {
				return fn.Resolve
			}
		case kinds.InterfaceDefinition:
			if fn, ok := r.(*InterfaceResolver).Fields[fieldName]; ok {
				return fn.Resolve
			}
		}
	}
	return graphql.DefaultResolveFn
}
func (c *registry) getFieldSubscribeFn(kind, typeName, fieldName string) graphql.FieldResolveFn {
	if r := c.getResolver(typeName); r != nil && kind == r.getKind() {
		switch kind {
		case kinds.ObjectDefinition:
			if fieldResolve, ok := r.(*ObjectResolver).Fields[fieldName]; ok {
				return fieldResolve.Subscribe
			}
		case kinds.InterfaceDefinition:
			if fieldResolve, ok := r.(*InterfaceResolver).Fields[fieldName]; ok {
				return fieldResolve.Subscribe
			}
		}
	}
	return nil
}
func (c *registry) buildComplexType(astType ast.Type) (graphql.Type, error) {
	switch kind := astType.GetKind(); kind {
	case kinds.List:
		t, err := c.buildComplexType(astType.(*ast.List).Type)
		if err != nil {
			return nil, err
		}
		return graphql.NewList(t), nil
	case kinds.NonNull:
		t, err := c.buildComplexType(astType.(*ast.NonNull).Type)
		if err != nil {
			return nil, err
		}
		return graphql.NewNonNull(t), nil
	case kinds.Named:
		t := astType.(*ast.Named)
		return c.getType(t.Name.Value)
	}
	return nil, fmt.Errorf("invalid kind")
}
func getDescription(node ast.DescribableNode) string {
	if desc := node.GetDescription(); desc != nil {
		return desc.Value
	}
	return ""
}
func getDefaultValue(input *ast.InputValueDefinition) interface{} {
	if value := input.DefaultValue; value != nil {
		return value.GetValue()
	}
	return nil
}