package main import ( "bytes" "flag" "fmt" "go/format" "os" "strings" "text/template" "gitea.ckfah.com/go-script/logger" "gitea.ckfah.com/go-script/utils" ) type ExType string const ( ServiceType = ExType("service.go") ThirdType = ExType("third.go") ) type Controller struct { RouterName string URouterName string Service string UserGin bool Comment string ExType ExType } // func (c Controller) ExceptionType() string { return string(c.ExType) } // func (c Controller) GetServiceFile() string { return utils.UnMarshal(fmt.Sprintf("%sService.go", c.Service)) } func (c Controller) GetControllerFile() string { return utils.UnMarshal(fmt.Sprintf("%sController.go", c.Service)) } func (c Controller) GetDtoFile() string { return utils.UnMarshal(fmt.Sprintf("%sDto.go", c.Service)) } // third func (c Controller) GetThirdName() string { return utils.UnMarshal(fmt.Sprintf("%sThird.go", c.Service)) } func (c Controller) ThirdName() string { return fmt.Sprintf("%sThird", c.Service) } func (c Controller) ThirdServiceApolloName() string { return strings.ReplaceAll(utils.UnMarshal(c.Service), "_", "-") } // 处理 ! func NewController(router string, serviceName string) Controller { // 空 if router == "" || serviceName == "" { logger.FatalFH("router_name 和 service_name 不能为空!!!", printHelp) } // 非法字符 ! if serviceName[0] >= '0' && serviceName[0] <= '9' { logger.FatalFH("-s=? 不能首字母是数字", printHelp) } if router[0] >= '0' && router[0] <= '9' { logger.FatalFH("-t=? 不能首字母是数字", printHelp) } // 保存最原始的r oldRouter := router router = strings.TrimPrefix(router, "/") router = strings.TrimSuffix(router, "/") // add / oldRouter = "/" + router // r 去除service_name //if strings.HasPrefix(router, serviceName) { // router = strings.TrimPrefix(router, serviceName) //} // service-name 转换为 驼峰 serviceName = utils.Marshal(strings.ReplaceAll(serviceName, "-", "_")) if strings.HasSuffix(serviceName, "Service") { serviceName = strings.TrimSuffix(serviceName, "Service") } if strings.HasSuffix(serviceName, "Controller") { serviceName = strings.TrimSuffix(serviceName, "Controller") } if strings.HasSuffix(serviceName, "Third") { serviceName = strings.TrimSuffix(serviceName, "Third") } // 转换为下划线 !!! if strings.Contains(router, "/") { split := strings.Split(router, "/") router = strings.Join(split, "_") } router = strings.ReplaceAll(router, "-", "_") // 初始化!!!! return Controller{ RouterName: utils.Marshal(router), URouterName: oldRouter, Service: serviceName, } } func (c Controller) ContextName() string { if userGin { return "*gin.Context" } return "*engines.Context" } func (c Controller) Common() string { if c.Comment == "" { return "" } return fmt.Sprintf("// %s", c.Comment) } func (c Controller) GetPath() string { return c.URouterName } func (c Controller) ControllerName() string { if c.Service == "" { logger.FatalF("-s 不能为空!!!!,否则无法生成模版") } return fmt.Sprintf("%s%s", LowerName(c.Service), "Controller") } func (c Controller) FuncName() string { return UpperName(c.RouterName) } func (c Controller) RequestName() string { return fmt.Sprintf("%s%s", UpperName(c.RouterName), "Request") } func (c Controller) ServiceName() string { if c.Service == "" { logger.FatalF("-s 不能为空!!!!,否则无法生成模版") } return fmt.Sprintf("%s%s", LowerName(c.Service), "Service") } func (c Controller) Params() string { return "params" } func LowerName(str string) string { if str[0] >= 'A' && str[0] <= 'Z' { newStr := []byte(str) newStr[0] = newStr[0] + 32 return string(newStr) } return str } func UpperName(str string) string { if str[0] >= 'a' && str[0] <= 'z' { newStr := []byte(str) newStr[0] = newStr[0] - 32 return string(newStr) } return str } func NewJsonTag(str string) string { return fmt.Sprintf("`json:\"%s\" binding:\"required\"`", str) } var newT = ` // ======================={{.GetControllerFile}}============================== type {{LowerName .ControllerName}} struct { } func New{{UpperName .ControllerName}}() *{{LowerName .ControllerName}} { return new({{LowerName .ControllerName}}) } var ( {{LowerName .ServiceName}} = service.New{{UpperName .ServiceName}}() ) // ======================={{.GetServiceFile}}============================== type {{LowerName .ServiceName}} struct { } func New{{UpperName .ServiceName}}() *{{LowerName .ServiceName}} { return new({{LowerName .ServiceName}}) } ` var ( controllerT = ` // ======================={{.GetControllerFile}}============================== {{.Common}} func(this *{{.ControllerName}}){{.FuncName}}(ctx {{.ContextName}}){ request := new(vo.{{.RequestName}}) err := ctx.BindJSON(request) if err != nil { logger.Warnc(ctx, "[{{.FuncName}}] bind params err,err=%v", err) common.FailJson(ctx, exception.ParamsBindError) return } logger.Infoc(ctx, "[{{.FuncName}}] start,request=%+v", request) result, cerr := {{.ServiceName}}.{{.FuncName}}(ctx, &request.Params) if cerr != nil { logger.Warnc(ctx, "[{{.FuncName}}] end err,err=%v", cerr) common.FailJson(ctx, cerr) return } logger.Infoc(ctx, "[{{.FuncName}}] end,result=%+v", result) common.SuccessJson(ctx, result) }` ) var ( dtoT = ` // ======================={{.GetDtoFile}}============================== {{.Common}} type {{UpperName .FuncName}}Request struct { Params dto.{{UpperName .FuncName}}Params {{NewJsonTag .Params}} } type {{UpperName .FuncName}}Params struct { } type {{UpperName .FuncName}}Result struct { } ` ) var ( serviceT = ` // ======================={{.GetServiceFile}}============================== {{.Common}} func (this *{{LowerName .ServiceName}}) {{UpperName .FuncName}}(context {{.ContextName}}, params *dto.{{UpperName .FuncName}}Params) (*dto.{{UpperName .FuncName}}Result, cerror.Cerror) { return nil, nil } ` ) var ( thirdT = ` // ==========================={{.GetThirdName}}=========================== // api-doc-address: type {{LowerName .ThirdName}} struct { } func New{{UpperName .ThirdName}}() *{{LowerName .ThirdName}} { return &{{LowerName .ThirdName}}{} } const ( _{{UpperName .ThirdName}}ServerName = "{{.ThirdServiceApolloName}}" ) func (*{{LowerName .ThirdName}}) GetServerName() string { return _{{UpperName .ThirdName}}ServerName } {{.Common}} func (this *{{LowerName .ThirdName}}) {{UpperName .FuncName}}(ctx {{.ContextName}},params *dto.{{UpperName .FuncName}}Params) (*dto.{{UpperName .FuncName}}Response, cerror.Cerror) { path := "{{.GetPath}}" response := new(dto.{{UpperName .FuncName}}Response) err := util.HttpRequestAndDecode(ctx, this.GetServerName(), path, params, response) if err != nil { logger.Warnc(ctx, "[{{UpperName .FuncName}}] request err,params=%+v,err=%v", params, err) return nil, exception.{{UpperName .FuncName}}Error(err) } return response, nil } ` ) var ( thirdDtoT = ` // ======================={{.GetDtoFile}}============================== {{.Common}} type {{UpperName .FuncName}}Params struct { } type {{UpperName .FuncName}}Response struct { } ` ) var ( apolloConfigT = ` //======================= config/apollo/namespaces.json ======================= { "name": "{{.ThirdServiceApolloName}}", "keys": [ { "name": "{{.ThirdServiceApolloName}}.host", "mapTo": "host" }, { "name": "{{.ThirdServiceApolloName}}.key", "mapTo": "key" }, { "name": "{{.ThirdServiceApolloName}}.name", "mapTo": "name" } ] } //======================= apollo添加properties,注意host key======================= # {{.ThirdServiceApolloName}} 服务 {{.ThirdServiceApolloName}}.host= {{.ThirdServiceApolloName}}.key= {{.ThirdServiceApolloName}}.name={{.ThirdServiceApolloName}} //=======================如果不是apollo,请在env.ini中添加,注意host key======================= ;{{.ThirdServiceApolloName}} 服务 [{{.ThirdServiceApolloName}}] host= key= name={{.ThirdServiceApolloName}} ` ) var ( exceptionServiceT = ` // ======================{{.ExceptionType}}================================== {{UpperName .FuncName}}Error = util.NewSCerror({{LowerName .FuncName}}ErrorCode) ` ) var ( exceptionThirdT = ` // ======================{{.ExceptionType}}================================== {{UpperName .FuncName}}Error = util.NewECerror({{LowerName .FuncName}}ErrorCode) ` ) var ( common string url string service string gThird bool // 生成third helps bool onlyDto bool onlyMew bool onlyService bool onlyController bool userGin bool ) func main() { flag.StringVar(&url, "r", "", "请求路由,比如/echo,生成Echo方法,/user/list生成UserList,必须传递") flag.StringVar(&service, "s", "", "生成的Service/Controller名字,比如 user,则生成userService,必须传递") flag.BoolVar(&helps, "h", false, "帮助!!") flag.BoolVar(&gThird, "t", false, "生成third,注意也是复用router 和 service_name,所以必须传递-r -s!!") flag.BoolVar(&onlyDto, "od", false, "比如 -od 只生成Dto对象") flag.BoolVar(&onlyMew, "on", false, "只生成New方法") flag.BoolVar(&onlyService, "os", false, "只生成Service方法") flag.BoolVar(&onlyController, "oc", false, "只生成Controller方法") flag.BoolVar(&userGin, "ug", false, "使用gin框架,默认是gauss") flag.StringVar(&common, "c", "", "方法注释!!service方法和controller方法注释是一样的奥!!不传不生成") Init() t := template.New("") t = t.Funcs(template.FuncMap{ "LowerName": LowerName, "UpperName": UpperName, "NewJsonTag": NewJsonTag, "UtilUnMarshal": utils.UnMarshal, }) controller := NewController(url, service) controller.UserGin = userGin controller.Comment = common fmt.Printf("==================touch file=======================\n") if gThird { controller.ExType = ThirdType fmt.Printf("third: %s\ndto: %s\n注意配置 apollo or env\n", controller.GetThirdName(), controller.GetDtoFile(), ) exec(t, thirdT, controller) exec(t, thirdDtoT, controller) execNotFormat(t, apolloConfigT, controller) execNotFormat(t, exceptionThirdT, controller) os.Exit(-1) } controller.ExType = ServiceType fmt.Printf("controller: %s\nservice: %s\ndto: %s\n\n", controller.GetControllerFile(), controller.GetServiceFile(), controller.GetDtoFile(), ) if onlyMew { exec(t, newT, controller) os.Exit(-1) } if onlyController { exec(t, controllerT, controller) os.Exit(-1) } if onlyDto { exec(t, dtoT, controller) os.Exit(-1) } if onlyService { exec(t, serviceT, controller) execNotFormat(t, exceptionServiceT, controller) os.Exit(-1) } exec(t, newT, controller) exec(t, controllerT, controller) exec(t, dtoT, controller) exec(t, serviceT, controller) execNotFormat(t, exceptionServiceT, controller) os.Exit(-1) } func exec(t *template.Template, str string, data interface{}) { parse, err := t.Parse(str) if err != nil { panic(err) } buffer := &bytes.Buffer{} err = parse.Execute(buffer, data) if err != nil { panic(err) } source, err := format.Source(buffer.Bytes()) if err != nil { panic(err) } fmt.Printf("%s\n", source) } func execNotFormat(t *template.Template, str string, data interface{}) { parse, err := t.Parse(str) if err != nil { panic(err) } buffer := &bytes.Buffer{} err = parse.Execute(buffer, data) if err != nil { panic(err) } fmt.Printf("%s\n", buffer.Bytes()) } func Init() { flag.Parse() if helps { printHelp() os.Exit(-1) } } func printHelp() { fmt.Println(`================go-new help===================== go-new -r=/user/list -s=user Option:`) flag.PrintDefaults() }