美文网首页
golang利用模板生成Repository/Service C

golang利用模板生成Repository/Service C

作者: EasyNetCN | 来源:发表于2021-07-29 15:06 被阅读0次

不支持多个相同类型的参数

package utility

import (
    "fmt"
    "html/template"
    "io/ioutil"
    "os"
    "regexp"
    "sort"
    "strings"
    "testing"
)

type Repository struct {
    Name string
}

type Service struct {
    Name string
    Args []ServiceArg
}

func (s Service) NewFuncString() string {
    sb := new(strings.Builder)

    for _, arg := range s.Args {
        if strings.HasPrefix(arg.TypeName, "repository.") {
            sb.WriteString("repositoryContainer.")
            sb.WriteString(arg.TypeName[len("repository."):])
            sb.WriteString(",\n")
        } else {
            dotIndex := strings.LastIndex(arg.TypeName, ".")

            if dotIndex > -1 {
                str := arg.TypeName[strings.LastIndex(arg.TypeName, ".")+1:]

                sb.WriteString(strings.ToLower(str[0:1]))
                sb.WriteString(str[1:])
                sb.WriteString(",\n")
            } else {
                sb.WriteString(strings.ToLower(arg.TypeName[0:1]))
                sb.WriteString(arg.TypeName[1:])
                sb.WriteString(",\n")
            }

        }
    }

    return sb.String()
}

type ServiceArg struct {
    Name     string
    TypeName string
}

type RepositoryContext struct {
    Repositories []Repository
}

type ServiceContext struct {
    Services []Service
}

func (c *ServiceContext) NewFuncString() string {
    typeNames := make([]string, 0)
    typeNameMap := make(map[string]string)

    for _, s := range c.Services {
        for _, arg := range s.Args {
            typeName := arg.TypeName

            if strings.HasPrefix(typeName, "repository.") {
                typeName = "repository.RepositoryContainer"
            }

            if _, ok := typeNameMap[typeName]; !ok {
                typeNameMap[typeName] = typeName
                typeNames = append(typeNames, typeName)
            }
        }
    }

    sort.Strings(typeNames)

    sb := new(strings.Builder)

    for _, typeName := range typeNames {
        if strings.HasPrefix(typeName, "repository.") {
            sb.WriteString("repositoryContainer ")
            sb.WriteString(typeName)
            sb.WriteString(",\n")
        } else {
            dotIndex := strings.LastIndex(typeName, ".")

            if dotIndex > -1 {
                str := typeName[strings.LastIndex(typeName, ".")+1:]

                sb.WriteString(strings.ToLower(str[0:1]))
                sb.WriteString(str[1:])
                sb.WriteString(" ")
                sb.WriteString(typeName)
                sb.WriteString(",\n")
            } else {
                sb.WriteString(strings.ToLower(typeName[0:1]))
                sb.WriteString(typeName[1:])
                sb.WriteString(" ")
                sb.WriteString(typeName)
                sb.WriteString(",\n")
            }
        }

    }

    return sb.String()
}

func Test_GenerateRepositoryContainer(t *testing.T) {
    files, err1 := os.ReadDir("../repository")

    if err1 != nil {
        fmt.Println("parse file err:", err1)
        return
    }

    repositories := make([]Repository, 0)

    for _, file := range files {
        name := file.Name()

        if strings.HasSuffix(name, "_repository.go") {
            repositories = append(repositories, Repository{Name: UpperCamelCase(name[:len(name)-3])})
        }
    }

    if f, err := os.Stat("../repository/repository_container.go"); f != nil && err == nil {
        if err := os.Remove("../repository/repository_container.go"); err != nil {
            fmt.Println("remove file err:", err)
            return
        }
    }

    f, err2 := os.OpenFile("../repository/repository_container.go", os.O_CREATE|os.O_WRONLY, 0666)

    defer f.Close()

    if err2 != nil {
        fmt.Println("can not create output file,err:", err2)

        return
    }

    tpl, err3 := template.New("repository-container.tpl").ParseFiles("./repository-container.tpl")

    if err3 != nil {
        fmt.Println("parse file err:", err3)
        return
    }

    if err := tpl.Execute(f, &RepositoryContext{Repositories: repositories}); err != nil {
        fmt.Println("There was an error:", err.Error())
        return
    }
}

func Test_GenerateServiceContainer(t *testing.T) {
    files, err1 := os.ReadDir("../service")

    if err1 != nil {
        fmt.Println("parse file err:", err1)
        return
    }

    services := make([]Service, 0)

    for _, file := range files {
        filename := file.Name()

        if strings.HasSuffix(filename, "_service.go") {
            serviceName := UpperCamelCase(filename[:len(filename)-3])

            args, err2 := ServiceArgs(fmt.Sprintf("../service/%s", filename), serviceName)

            if err2 != nil {
                fmt.Println(err2)

                return
            }

            services = append(services, Service{Name: serviceName, Args: args})

        }
    }

    if f, err := os.Stat("../service/service_container.go"); f != nil && err == nil {
        if err := os.Remove("../service/service_container.go"); err != nil {
            fmt.Println("remove file err:", err)
            return
        }
    }

    f, err2 := os.OpenFile("../service/service_container.go", os.O_CREATE|os.O_WRONLY, 0666)

    defer f.Close()

    if err2 != nil {
        fmt.Println("can not create output file,err:", err2)

        return
    }

    tpl, err3 := template.New("service-container.tpl").ParseFiles("./service-container.tpl")

    if err3 != nil {
        fmt.Println("parse file err:", err3)
        return
    }

    if err := tpl.Execute(f, &ServiceContext{Services: services}); err != nil {
        fmt.Println("There was an error:", err.Error())
    }
}

func UpperCamelCase(txt string) string {
    sb := new(strings.Builder)

    strs := strings.Split(txt, "_")

    for _, str := range strs {
        sb.WriteString(strings.ToUpper(string(str[0])))
        sb.WriteString(str[1:])
    }

    return sb.String()
}

func ServiceArgs(filename, serviceName string) ([]ServiceArg, error) {
    content, err1 := ReadGoFile(filename)

    if err1 != nil {
        return nil, err1
    }

    args := make([]ServiceArg, 0)

    startTxt := fmt.Sprintf("New%s(", serviceName)

    firstIndex := strings.Index(content, startTxt) + len(startTxt)
    lastIndex := firstIndex + strings.Index(content[firstIndex:], ")")

    reg := regexp.MustCompile(`\s+`)

    strs := strings.Split(reg.ReplaceAllString(content[firstIndex:lastIndex], " "), ",")

    for _, str := range strs {
        txt := strings.TrimSpace(str)

        if len(txt) > 0 {
            args = append(args, Arg(txt))
        }
    }

    return args, nil
}

func Arg(str string) ServiceArg {
    strs := strings.Split(str, " ")

    return ServiceArg{Name: strings.TrimSpace(strs[0]), TypeName: strings.TrimSpace(strs[1])}
}

func ReadGoFile(fileName string) (string, error) {
    f, err := os.OpenFile(fileName, os.O_RDONLY, 0600)

    defer f.Close()

    if err != nil {
        return "", err
    } else {
        if bytes, err := ioutil.ReadAll(f); err != nil {
            return "", err
        } else {
            return string(bytes), nil
        }
    }
}

repository container template

package repository

import (
    "github.com/kataras/golog"
    "xorm.io/xorm"
)

type RepositoryContainer struct{
    {{range $repository := .Repositories -}}
    {{.Name}} {{.Name}} 
    {{end -}}
}

func NewRepositoryContainer(engine *xorm.Engine, logger *golog.Logger) *RepositoryContainer{
    return &RepositoryContainer{
        {{range $repository := .Repositories -}}
        {{.Name}}: New{{.Name}}(engine, logger),
        {{end -}}
    }
}

service container template

package service

import (
    "github.com/kataras/golog"
    "xorm.io/xorm"
)

type ServiceContainer struct{
    {{range $service := .Services -}}
    {{.Name}} {{.Name}} 
    {{end -}}
}

func NewServiceContainer({{.NewFuncString}}) *ServiceContainer{
    return &ServiceContainer{
        {{range $service := .Services -}}
        {{.Name}}: New{{.Name}}({{.NewFuncString}}),
        {{end -}}
    }
}

相关文章

网友评论

      本文标题:golang利用模板生成Repository/Service C

      本文链接:https://www.haomeiwen.com/subject/obaxvltx.html