func (fl fieldList) FuncName() string {
	out := ""
	for i, field := range fl {
		if i == 0 {
			out += "By"
		} else {
			out += "And"
		}
		out += snakeToProper(field.Column)
	}
	return out
}
FuncName gets the concatenated function argument descriptor in a
Spring Data Repository style i.e. <Verb>By(<Field>And)*(<Field>).
package main
import (
	"fmt"
	"log"
	"os"
	"strings"
	"text/template"
	"time"
)
func main() {
	models := []crudModel{
		{
			Type:            "ServiceInstanceDetails",
			PrimaryKeyType:  "string",
			PrimaryKeyField: "id",
			ExampleFields: map[string]interface{}{
				"Name":             "Hello",
				"Location":         "loc",
				"Url":              "https://google.com",
				"OtherDetails":     `{"some":["json","blob","here"]}`,
				"ServiceId":        "123-456-7890",
				"PlanId":           "planid",
				"SpaceGuid":        "0000-0000-0000",
				"OrganizationGuid": "1111-1111-1111",
			},
		},
		{
			Type:            "ServiceBindingCredentials",
			PrimaryKeyType:  "uint",
			PrimaryKeyField: "id",
			Keys: []fieldList{
				{
					{Type: "string", Column: "service_instance_id"},
					{Type: "string", Column: "binding_id"},
				},
				{
					{Type: "string", Column: "binding_id"},
				},
			},
			ExampleFields: map[string]interface{}{
				"ServiceId":         "1111-1111-1111",
				"ServiceInstanceId": "2222-2222-2222",
				"BindingId":         "0000-0000-0000",
				"OtherDetails":      `{"some":["json","blob","here"]}`,
			},
		},
		{
			Type:            "ProvisionRequestDetails",
			PrimaryKeyType:  "uint",
			PrimaryKeyField: "id",
			ExampleFields: map[string]interface{}{
				"ServiceInstanceId": "2222-2222-2222",
				"RequestDetails":    `{"some":["json","blob","here"]}`,
			},
		},
		{
			Type:            "TerraformDeployment",
			PrimaryKeyType:  "string",
			PrimaryKeyField: "id",
			Keys:            []fieldList{},
			ExampleFields: map[string]interface{}{
				"Workspace":            "{}",
				"LastOperationType":    "create",
				"LastOperationState":   `in progress`,
				"LastOperationMessage": `Started 2018-01-01`,
			},
		},
	}
	for i, model := range models {
		pk := fieldList{{Type: model.PrimaryKeyType, Column: model.PrimaryKeyField}}
		models[i].Keys = append(model.Keys, pk)
	}
	createDao(models)
	createDaoTest(models)
}
func createDao(models []crudModel) {
	f, err := os.Create("dao.go")
	die(err)
	defer f.Close()
	daoTemplate.Execute(f, struct {
		Timestamp time.Time
		Models    []crudModel
	}{
		Timestamp: time.Now(),
		Models:    models,
	})
}
func createDaoTest(models []crudModel) {
	f, err := os.Create("dao_test.go")
	die(err)
	defer f.Close()
	daoTestTemplate.Execute(f, struct {
		Timestamp time.Time
		Models    []crudModel
	}{
		Timestamp: time.Now(),
		Models:    models,
	})
}
func die(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
type crudModel struct {
	Type            string
	PrimaryKeyType  string
	PrimaryKeyField string
	ExampleFields   map[string]interface{}
	Keys            []fieldList
}
type fieldList []crudField
func (fl fieldList) WhereClause() string {
	var cols []string
	for _, field := range fl {
		cols = append(cols, field.Column+" = ?")
	}
	colf := strings.Join(cols, " AND ")
	return fmt.Sprintf("Where(%q, %s)", colf, fl.CallParams())
}