func generify(template string, sym symbols) (out string) {
	out = template
	out = strings.Replace(out, elementTypeSymbol, sym.T, -1)
	out = strings.Replace(out, sliceSliceTypeSymbol, "[][]"+sym.T, -1)
	out = strings.Replace(out, sliceTypeSymbol, sym.ST, -1)
	return
}
replace the placeholders by the correct symbols
package main
import (
	"bytes"
	"flag"
	"fmt"
	"go/format"
	"golang.org/x/tools/go/packages"
	"io/ioutil"
	"os"
	"sort"
	"strings"
)
const (
	elementTypeSymbol    = "ElementType"
	sliceTypeSymbol      = "SliceType"
	sliceSliceTypeSymbol = "SliceSliceType"  
)
var (
	unitType    = flag.String("T", "", "Type for which to generate data")
	sliceType   = flag.String("S", "", "Corresponding Slice Type for T")
	packag      = flag.String("P", "types", "Package for which to generate")
	ofilename   = flag.String("N", "", "name for the generated file (_hasgo.go will be appended)")
	numberTypes = map[string]struct{}{
		"int":     {},
		"int32":   {},
		"int64":   {},
		"uint":    {},
		"uint32":  {},
		"uint64":  {},
		"float":   {},
		"float32": {},
		"float64": {},
	}
	stringTypes = map[string]struct{}{
		"string": {},
	}
)
func check(e error) {
	if e != nil {
		panic(e)
	}
}
type symbols struct {
	T, ST string
}
type generator struct {
	buf     bytes.Buffer         
	pkg     string               
	imports map[string]struct{}  
}
func main() {
	flag.Parse()
	fmt.Printf("type: %v - slice: %v\n", *unitType, *sliceType)
	sym := symbols{*unitType, *sliceType}
	g := generator{
		imports: map[string]struct{}{},
		pkg:     *packag,
	}
	g.parsePackage(os.Args, nil)
	g.generate(sym)
	filename := fmt.Sprintf("%v_hasgo.go", *sliceType)
	if ofilename != nil && *ofilename != "" {
		filename = fmt.Sprintf("%v_hasgo.go", *ofilename)
	}
	err := ioutil.WriteFile(filename, g.format(), 0644)
	if err != nil {
		panic(err)
	}
}
func validFunction(function, T string) bool {
	domains, ok := funcDomains[function]
	if !ok {
		return false
	}
	for _, d := range domains {
		switch d {
		case ForNumbers:
			if _, ok := numberTypes[T]; ok {
				return true
			}
			break
		case ForStrings:
			if _, ok := stringTypes[T]; ok {
				return true
			}
			break
		case ForStructs:
			if _, ok := numberTypes[T]; !ok {
				if _, ok := stringTypes[T]; !ok {
					return true
				}
			}
			break
		}
	}
	return false
}
func (g *generator) generate(s symbols) {
	funcs := []string{}
	for function := range hasgoTemplates {
		funcs = append(funcs, function)
	}
	sort.Strings(funcs)
	for _, function := range funcs {
		template := hasgoTemplates[function]
		if !validFunction(function, s.T) {
			continue
		}
		template, imports := extractImports(template)
		g.addImports(imports)
		g.printf("// =============== %v =================\n", function)
		g.print(generify(template, s))
		g.newline()
	}
}
func extractImports(template string) (outtemp string, imports []string) {
	lines := strings.Split(template, "\n")
	nonImportLines := []string{}
	for i := 0; i < len(lines); {
		line := lines[i]
		if strings.Contains(line, "import") {
			if strings.Contains(line, "(") {
				i++
				line := lines[i]
				for !strings.Contains(line, ")") {
					imports = append(imports, line)
					i++
					line = lines[i]
				}
				i++
				continue
			} else {
				line = strings.TrimSpace(line)[len("import"):]
				imports = append(imports, line)
				i++
				continue
			}
		}
		nonImportLines = append(nonImportLines, line)
		i++
	}
	return strings.Join(nonImportLines, "\n"), imports
}