package main import ( "bytes" "flag" "fmt" "html/template" "os" "strings" ) var Auto = &AutoApi{} type AutoApi struct { Topic string Key string } func main() { fs := flag.NewFlagSet("service", flag.ExitOnError) fs.StringVar(&Auto.Topic, "t", "", "set topic") fs.StringVar(&Auto.Key, "k", "", "set key") // 解析命令行参数 if err := fs.Parse(os.Args[1:]); err != nil { _, _ = fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } if Auto.Key == "" || Auto.Topic == "" { fmt.Fprintf(os.Stderr, "Error: must set -k or -t\n") return } path, _ := os.Getwd() basePath := fmt.Sprintf("%s/internal/service/queue/", path) c := basePath + "consumer/" p := basePath + "producer/" t := basePath + "types/" name := camelString(Auto.Key) topic := camelString(Auto.Topic) tt := T{ Name: name, Key: Auto.Key, } var err error defer func() { if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Error: %v\n", err) } }() tc, err := createTmp(tt, tTemp) if err != nil { return } err = appendFile(fmt.Sprintf("%s%s.go", t, Auto.Topic), tc) if err != nil { return } pt := P{ Name: name, Topic: topic, } pc, err := createTmp(pt, pTemp) if err != nil { return } err = appendFile(fmt.Sprintf("%s%s.go", p, Auto.Topic), pc) if err != nil { return } pkg := strings.ReplaceAll(Auto.Topic, "_", "") ct := C{ Name: name, Pkg: pkg, } cc, err := createTmp(ct, cTemp) if err != nil { return } err = createFile(fmt.Sprintf("%s%s/%s.go", c, pkg, Auto.Key), cc) if err != nil { return } at := A{ Name: name, FName: strings.ToLower(string(name[0])) + name[1:], } ac, err := createTmp(at, aTemp) if err != nil { return } err = appendFile(fmt.Sprintf("%s%s/consume.go", c, pkg), ac) if err != nil { return } } type T struct { Name string Key string } var tTemp = ` const {{ .UserId }}Key = "{{ .Key }}" type {{ .UserId }} struct { }` type P struct { Name string Topic string } var pTemp = ` func (p {{ .Topic }}) {{ .UserId }}(data types.{{ .UserId }}) { _ = AP.Produce(p.ctx, p.topic, types.{{ .UserId }}Key, data) }` type C struct { Name string Pkg string } var cTemp = `package {{ .Pkg }} import ( "joybuywork/internal/service/queue/types" "joybuywork/internal/utils/logic" ) type {{ .UserId }} struct { logic.Logic Req *types.{{ .UserId }} } func (s *{{ .UserId }}) Exec() (err error) { return }` type A struct { Name string FName string } var aTemp = ` func {{ .FName }}(ctx *consumer.Ctx) (err error) { var val types.{{ .UserId }} err = ctx.Parse(&val) if err != nil { return } var container = new({{ .UserId }}) { container.Init(ctx.Context()) container.Req = &val } return logic.Run(container) } ` // 蛇形转驼峰 func camelString(s string) string { data := make([]byte, 0, len(s)) j := false k := false num := len(s) - 1 for i := 0; i <= num; i++ { d := s[i] if k == false && d >= 'A' && d <= 'Z' { k = true } if d >= 'a' && d <= 'z' && (j || k == false) { d = d - 32 j = false k = true } if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' { j = true continue } data = append(data, d) } return string(data[:]) } func createTmp(content any, parse string) (text string, err error) { t, err := template.New("tmp.tpl").Parse(parse) if err != nil { return } var buf bytes.Buffer err = t.Execute(&buf, content) if err != nil { return } return buf.String(), nil } func appendFile(filename, content string) (err error) { file, err := os.OpenFile(filename, os.O_APPEND|os.O_RDWR, 0777) defer file.Close() if err != nil { return err } _, err = file.WriteString(content) return } func createFile(filename, content string) (err error) { file, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777) defer file.Close() if err != nil { return err } _, err = file.WriteString(content) return }