Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5c560e8ba | ||
|
|
bed494d904 | ||
|
|
2dfecda465 | ||
|
|
3ebb1e0221 | ||
|
|
348184904c | ||
|
|
7a27fa50a1 | ||
|
|
8d4951c990 | ||
|
|
6e57f6c527 | ||
|
|
b9ac51b6c3 | ||
|
|
702e8d79ce | ||
|
|
95a9dabf8b | ||
|
|
bae66c49c2 |
@@ -76,7 +76,6 @@ func (rw *RollingWindow) updateOffset() {
|
|||||||
span := rw.span()
|
span := rw.span()
|
||||||
if span > 0 {
|
if span > 0 {
|
||||||
offset := rw.offset
|
offset := rw.offset
|
||||||
// reset expired buckets
|
|
||||||
start := offset + 1
|
start := offset + 1
|
||||||
steps := start + span
|
steps := start + span
|
||||||
var remainder int
|
var remainder int
|
||||||
@@ -84,15 +83,16 @@ func (rw *RollingWindow) updateOffset() {
|
|||||||
remainder = steps - rw.size
|
remainder = steps - rw.size
|
||||||
steps = rw.size
|
steps = rw.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset expired buckets
|
||||||
for i := start; i < steps; i++ {
|
for i := start; i < steps; i++ {
|
||||||
rw.win.resetBucket(i)
|
rw.win.resetBucket(i)
|
||||||
offset = i
|
|
||||||
}
|
}
|
||||||
for i := 0; i < remainder; i++ {
|
for i := 0; i < remainder; i++ {
|
||||||
rw.win.resetBucket(i)
|
rw.win.resetBucket(i)
|
||||||
offset = i
|
|
||||||
}
|
}
|
||||||
rw.offset = offset
|
|
||||||
|
rw.offset = (offset + span) % rw.size
|
||||||
rw.lastTime = timex.Now()
|
rw.lastTime = timex.Now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ func main() {
|
|||||||
var allowed, denied int32
|
var allowed, denied int32
|
||||||
var wait sync.WaitGroup
|
var wait sync.WaitGroup
|
||||||
for i := 0; i < *threads; i++ {
|
for i := 0; i < *threads; i++ {
|
||||||
|
i := i
|
||||||
wait.Add(1)
|
wait.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ goctl api -o greet.api
|
|||||||
you can check it by curl:
|
you can check it by curl:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -i http://localhost:8888/greet/from/you
|
curl -i http://localhost:8888/from/you
|
||||||
```
|
```
|
||||||
|
|
||||||
the response looks like:
|
the response looks like:
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
|
|||||||
默认侦听在 8888 端口(可以在配置文件里修改),可以通过 curl 请求:
|
默认侦听在 8888 端口(可以在配置文件里修改),可以通过 curl 请求:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -i http://localhost:8888/greet/from/you
|
curl -i http://localhost:8888/from/you
|
||||||
```
|
```
|
||||||
|
|
||||||
返回如下:
|
返回如下:
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ version := $(shell /bin/date "+%Y-%m-%d %H:%M")
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" goctl.go
|
go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" goctl.go
|
||||||
command -v upx &> /dev/null && upx goctl
|
$(if $(shell command -v upx), upx goctl)
|
||||||
mac:
|
mac:
|
||||||
GOOS=darwin go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-darwin goctl.go
|
GOOS=darwin go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-darwin goctl.go
|
||||||
command -v upx &> /dev/null && upx goctl-darwin
|
$(if $(shell command -v upx), upx goctl-darwin)
|
||||||
win:
|
win:
|
||||||
GOOS=windows go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl.exe goctl.go
|
GOOS=windows go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl.exe goctl.go
|
||||||
command -v upx &> /dev/null && upx goctl.exe
|
$(if $(shell command -v upx), upx goctl.exe)
|
||||||
linux:
|
linux:
|
||||||
GOOS=linux go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-linux goctl.go
|
GOOS=linux go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-linux goctl.go
|
||||||
command -v upx &> /dev/null && upx goctl-linux
|
$(if $(shell command -v upx), upx goctl-linux)
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ type response struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
service {{.serviceName}} {
|
service {{.serviceName}} {
|
||||||
@handler // TODO: set handler name and delete this comment
|
@handler GetUser // TODO: set handler name and delete this comment
|
||||||
get /users/id/:userId(request) returns(response)
|
get /users/id/:userId(request) returns(response)
|
||||||
|
|
||||||
@handler // TODO: set handler name and delete this comment
|
@handler CreateUser // TODO: set handler name and delete this comment
|
||||||
post /users/create(request)
|
post /users/create(request)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/logrusorgru/aurora"
|
"github.com/logrusorgru/aurora"
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/core/logx"
|
"github.com/tal-tech/go-zero/core/logx"
|
||||||
apiformat "github.com/tal-tech/go-zero/tools/goctl/api/format"
|
apiformat "github.com/tal-tech/go-zero/tools/goctl/api/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/api/parser"
|
||||||
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
const tmpFile = "%s-%d"
|
const tmpFile = "%s-%d"
|
||||||
@@ -28,6 +28,8 @@ var tmpDir = path.Join(os.TempDir(), "goctl")
|
|||||||
func GoCommand(c *cli.Context) error {
|
func GoCommand(c *cli.Context) error {
|
||||||
apiFile := c.String("api")
|
apiFile := c.String("api")
|
||||||
dir := c.String("dir")
|
dir := c.String("dir")
|
||||||
|
namingStyle := c.String("style")
|
||||||
|
|
||||||
if len(apiFile) == 0 {
|
if len(apiFile) == 0 {
|
||||||
return errors.New("missing -api")
|
return errors.New("missing -api")
|
||||||
}
|
}
|
||||||
@@ -35,10 +37,10 @@ func GoCommand(c *cli.Context) error {
|
|||||||
return errors.New("missing -dir")
|
return errors.New("missing -dir")
|
||||||
}
|
}
|
||||||
|
|
||||||
return DoGenProject(apiFile, dir)
|
return DoGenProject(apiFile, dir, namingStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoGenProject(apiFile, dir string) error {
|
func DoGenProject(apiFile, dir, style string) error {
|
||||||
p, err := parser.NewParser(apiFile)
|
p, err := parser.NewParser(apiFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -48,15 +50,21 @@ func DoGenProject(apiFile, dir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg, err := config.NewConfig(style)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
logx.Must(util.MkdirIfNotExist(dir))
|
logx.Must(util.MkdirIfNotExist(dir))
|
||||||
logx.Must(genEtc(dir, api))
|
logx.Must(genEtc(dir, cfg, api))
|
||||||
logx.Must(genConfig(dir, api))
|
logx.Must(genConfig(dir, cfg, api))
|
||||||
logx.Must(genMain(dir, api))
|
logx.Must(genMain(dir, cfg, api))
|
||||||
logx.Must(genServiceContext(dir, api))
|
logx.Must(genServiceContext(dir, cfg, api))
|
||||||
logx.Must(genTypes(dir, api))
|
logx.Must(genTypes(dir, cfg, api))
|
||||||
logx.Must(genHandlers(dir, api))
|
logx.Must(genRoutes(dir, cfg, api))
|
||||||
logx.Must(genRoutes(dir, api))
|
logx.Must(genHandlers(dir, cfg, api))
|
||||||
logx.Must(genLogic(dir, api))
|
logx.Must(genLogic(dir, cfg, api))
|
||||||
|
logx.Must(genMiddleware(dir, cfg, api))
|
||||||
|
|
||||||
if err := backupAndSweep(apiFile); err != nil {
|
if err := backupAndSweep(apiFile); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ func TestHasImportApi(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.True(t, hasInline)
|
assert.True(t, hasInline)
|
||||||
|
|
||||||
validate(t, filename)
|
validate(t, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,15 +559,30 @@ func TestNestTypeApi(t *testing.T) {
|
|||||||
err := ioutil.WriteFile(filename, []byte(nestTypeApi), os.ModePerm)
|
err := ioutil.WriteFile(filename, []byte(nestTypeApi), os.ModePerm)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
defer os.Remove(filename)
|
defer os.Remove(filename)
|
||||||
|
|
||||||
_, err = parser.NewParser(filename)
|
_, err = parser.NewParser(filename)
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCamelStyle(t *testing.T) {
|
||||||
|
filename := "greet.api"
|
||||||
|
err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
_, err = parser.NewParser(filename)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
validateWithCamel(t, filename, "GoZero")
|
||||||
|
}
|
||||||
|
|
||||||
func validate(t *testing.T, api string) {
|
func validate(t *testing.T, api string) {
|
||||||
|
validateWithCamel(t, api, "gozero")
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateWithCamel(t *testing.T, api, camel string) {
|
||||||
dir := "_go"
|
dir := "_go"
|
||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
err := DoGenProject(api, dir)
|
err := DoGenProject(api, dir, camel)
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
configFile = "config.go"
|
configFile = "config"
|
||||||
configTemplate = `package config
|
configTemplate = `package config
|
||||||
|
|
||||||
import {{.authImport}}
|
import {{.authImport}}
|
||||||
@@ -31,8 +33,13 @@ type Config struct {
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func genConfig(dir string, api *spec.ApiSpec) error {
|
func genConfig(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
fp, created, err := util.MaybeCreateFile(dir, configDir, configFile)
|
filename, err := format.FileNamingFormat(cfg.NamingFormat, configFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fp, created, err := util.MaybeCreateFile(dir, configDir, filename+".go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -20,8 +22,13 @@ Port: {{.port}}
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func genEtc(dir string, api *spec.ApiSpec) error {
|
func genEtc(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
fp, created, err := util.MaybeCreateFile(dir, etcDir, fmt.Sprintf("%s.yaml", api.Service.Name))
|
filename, err := format.FileNamingFormat(cfg.NamingFormat, api.Service.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fp, created, err := util.MaybeCreateFile(dir, etcDir, fmt.Sprintf("%s.yaml", filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,18 @@ package gogen
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,13 +54,8 @@ type Handler struct {
|
|||||||
HasRequest bool
|
HasRequest bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func genHandler(dir string, group spec.Group, route spec.Route) error {
|
func genHandler(dir string, cfg *config.Config, group spec.Group, route spec.Route) error {
|
||||||
handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
|
handler := getHandlerName(route)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("missing handler annotation for %q", route.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
handler = getHandlerName(handler)
|
|
||||||
if getHandlerFolderPath(group, route) != handlerDir {
|
if getHandlerFolderPath(group, route) != handlerDir {
|
||||||
handler = strings.Title(handler)
|
handler = strings.Title(handler)
|
||||||
}
|
}
|
||||||
@@ -65,27 +64,24 @@ func genHandler(dir string, group spec.Group, route spec.Route) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return doGenToFile(dir, handler, group, route, Handler{
|
return doGenToFile(dir, handler, cfg, group, route, Handler{
|
||||||
ImportPackages: genHandlerImports(group, route, parentPkg),
|
ImportPackages: genHandlerImports(group, route, parentPkg),
|
||||||
HandlerName: handler,
|
HandlerName: handler,
|
||||||
RequestType: util.Title(route.RequestType.Name),
|
RequestType: util.Title(route.RequestType.Name),
|
||||||
LogicType: strings.TrimSuffix(strings.Title(handler), "Handler") + "Logic",
|
LogicType: strings.Title(getLogicName(route)),
|
||||||
Call: strings.Title(strings.TrimSuffix(handler, "Handler")),
|
Call: strings.Title(strings.TrimSuffix(handler, "Handler")),
|
||||||
HasResp: len(route.ResponseType.Name) > 0,
|
HasResp: len(route.ResponseType.Name) > 0,
|
||||||
HasRequest: len(route.RequestType.Name) > 0,
|
HasRequest: len(route.RequestType.Name) > 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func doGenToFile(dir, handler string, group spec.Group, route spec.Route, handleObj Handler) error {
|
func doGenToFile(dir, handler string, cfg *config.Config, group spec.Group, route spec.Route, handleObj Handler) error {
|
||||||
if getHandlerFolderPath(group, route) != handlerDir {
|
filename, err := format.FileNamingFormat(cfg.NamingFormat, handler)
|
||||||
handler = strings.Title(handler)
|
if err != nil {
|
||||||
}
|
return err
|
||||||
filename := strings.ToLower(handler)
|
|
||||||
if strings.HasSuffix(filename, "handler") {
|
|
||||||
filename = filename + ".go"
|
|
||||||
} else {
|
|
||||||
filename = filename + "handler.go"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filename = filename + ".go"
|
||||||
fp, created, err := apiutil.MaybeCreateFile(dir, getHandlerFolderPath(group, route), filename)
|
fp, created, err := apiutil.MaybeCreateFile(dir, getHandlerFolderPath(group, route), filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -111,10 +107,10 @@ func doGenToFile(dir, handler string, group spec.Group, route spec.Route, handle
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func genHandlers(dir string, api *spec.ApiSpec) error {
|
func genHandlers(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
for _, group := range api.Service.Groups {
|
for _, group := range api.Service.Groups {
|
||||||
for _, route := range group.Routes {
|
for _, route := range group.Routes {
|
||||||
if err := genHandler(dir, group, route); err != nil {
|
if err := genHandler(dir, cfg, group, route); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,14 +132,23 @@ func genHandlerImports(group spec.Group, route spec.Route, parentPkg string) str
|
|||||||
return strings.Join(imports, "\n\t")
|
return strings.Join(imports, "\n\t")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHandlerBaseName(handler string) string {
|
func getHandlerBaseName(route spec.Route) (string, error) {
|
||||||
handlerName := util.Untitle(handler)
|
handler, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
|
||||||
if strings.HasSuffix(handlerName, "handler") {
|
if !ok {
|
||||||
handlerName = strings.ReplaceAll(handlerName, "handler", "")
|
return "", fmt.Errorf("missing handler annotation for %q", route.Path)
|
||||||
} else if strings.HasSuffix(handlerName, "Handler") {
|
|
||||||
handlerName = strings.ReplaceAll(handlerName, "Handler", "")
|
|
||||||
}
|
}
|
||||||
return handlerName
|
|
||||||
|
for _, char := range handler {
|
||||||
|
if !unicode.IsDigit(char) && !unicode.IsLetter(char) {
|
||||||
|
return "", errors.New(fmt.Sprintf("route [%s] handler [%s] invalid, handler name should only contains letter or digit",
|
||||||
|
route.Path, handler))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler = strings.TrimSpace(handler)
|
||||||
|
handler = strings.TrimSuffix(handler, "handler")
|
||||||
|
handler = strings.TrimSuffix(handler, "Handler")
|
||||||
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHandlerFolderPath(group spec.Group, route spec.Route) string {
|
func getHandlerFolderPath(group spec.Group, route spec.Route) string {
|
||||||
@@ -159,6 +164,20 @@ func getHandlerFolderPath(group spec.Group, route spec.Route) string {
|
|||||||
return path.Join(handlerDir, folder)
|
return path.Join(handlerDir, folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHandlerName(handler string) string {
|
func getHandlerName(route spec.Route) string {
|
||||||
return getHandlerBaseName(handler) + "Handler"
|
handler, err := getHandlerBaseName(route)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler + "Handler"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLogicName(route spec.Route) string {
|
||||||
|
handler, err := getHandlerBaseName(route)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler + "Logic"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,10 +42,10 @@ func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func genLogic(dir string, api *spec.ApiSpec) error {
|
func genLogic(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
for _, g := range api.Service.Groups {
|
for _, g := range api.Service.Groups {
|
||||||
for _, r := range g.Routes {
|
for _, r := range g.Routes {
|
||||||
err := genLogicByRoute(dir, g, r)
|
err := genLogicByRoute(dir, cfg, g, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -52,16 +54,14 @@ func genLogic(dir string, api *spec.ApiSpec) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func genLogicByRoute(dir string, group spec.Group, route spec.Route) error {
|
func genLogicByRoute(dir string, cfg *config.Config, group spec.Group, route spec.Route) error {
|
||||||
handler, ok := util.GetAnnotationValue(route.Annotations, "server", "handler")
|
logic := getLogicName(route)
|
||||||
if !ok {
|
goFile, err := format.FileNamingFormat(cfg.NamingFormat, logic)
|
||||||
return fmt.Errorf("missing handler annotation for %q", route.Path)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = strings.TrimSuffix(handler, "handler")
|
goFile = goFile + ".go"
|
||||||
handler = strings.TrimSuffix(handler, "Handler")
|
|
||||||
filename := strings.ToLower(handler)
|
|
||||||
goFile := filename + "logic.go"
|
|
||||||
fp, created, err := util.MaybeCreateFile(dir, getLogicFolderPath(group, route), goFile)
|
fp, created, err := util.MaybeCreateFile(dir, getLogicFolderPath(group, route), goFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -102,8 +102,8 @@ func genLogicByRoute(dir string, group spec.Group, route spec.Route) error {
|
|||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
err = t.Execute(fp, map[string]string{
|
err = t.Execute(fp, map[string]string{
|
||||||
"imports": imports,
|
"imports": imports,
|
||||||
"logic": strings.Title(handler) + "Logic",
|
"logic": strings.Title(logic),
|
||||||
"function": strings.Title(strings.TrimSuffix(handler, "Handler")),
|
"function": strings.Title(strings.TrimSuffix(logic, "Logic")),
|
||||||
"responseType": responseString,
|
"responseType": responseString,
|
||||||
"returnString": returnString,
|
"returnString": returnString,
|
||||||
"request": requestString,
|
"request": requestString,
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,12 +42,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func genMain(dir string, api *spec.ApiSpec) error {
|
func genMain(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
name := strings.ToLower(api.Service.Name)
|
name := strings.ToLower(api.Service.Name)
|
||||||
if strings.HasSuffix(name, "-api") {
|
if strings.HasSuffix(name, "-api") {
|
||||||
name = strings.ReplaceAll(name, "-api", "")
|
name = strings.ReplaceAll(name, "-api", "")
|
||||||
}
|
}
|
||||||
goFile := name + ".go"
|
filename, err := format.FileNamingFormat(cfg.NamingFormat, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
goFile := filename + ".go"
|
||||||
fp, created, err := util.MaybeCreateFile(dir, "", goFile)
|
fp, created, err := util.MaybeCreateFile(dir, "", goFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var middlewareImplementCode = `
|
var middlewareImplementCode = `
|
||||||
@@ -30,9 +33,16 @@ func (m *{{.name}})Handle(next http.HandlerFunc) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func genMiddleware(dir string, middlewares []string) error {
|
func genMiddleware(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
|
var middlewares = getMiddleware(api)
|
||||||
for _, item := range middlewares {
|
for _, item := range middlewares {
|
||||||
filename := strings.TrimSuffix(strings.ToLower(item), "middleware") + "middleware" + ".go"
|
middlewareFilename := strings.TrimSuffix(strings.ToLower(item), "middleware") + "_middleware"
|
||||||
|
formatName, err := format.FileNamingFormat(cfg.NamingFormat, middlewareFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := formatName + ".go"
|
||||||
fp, created, err := util.MaybeCreateFile(dir, middlewareDir, filename)
|
fp, created, err := util.MaybeCreateFile(dir, middlewareDir, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/core/collection"
|
"github.com/tal-tech/go-zero/core/collection"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
routesFilename = "routes.go"
|
routesFilename = "routes"
|
||||||
routesTemplate = `// Code generated by goctl. DO NOT EDIT.
|
routesTemplate = `// Code generated by goctl. DO NOT EDIT.
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
@@ -62,7 +64,7 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func genRoutes(dir string, api *spec.ApiSpec) error {
|
func genRoutes(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
groups, err := getRoutes(api)
|
groups, err := getRoutes(api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,10 +123,16 @@ func genRoutes(dir string, api *spec.ApiSpec) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := path.Join(dir, handlerDir, routesFilename)
|
routeFilename, err := format.FileNamingFormat(cfg.NamingFormat, routesFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
routeFilename = routeFilename + ".go"
|
||||||
|
|
||||||
|
filename := path.Join(dir, handlerDir, routeFilename)
|
||||||
os.Remove(filename)
|
os.Remove(filename)
|
||||||
|
|
||||||
fp, created, err := apiutil.MaybeCreateFile(dir, handlerDir, routesFilename)
|
fp, created, err := apiutil.MaybeCreateFile(dir, handlerDir, routeFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -176,11 +184,8 @@ func getRoutes(api *spec.ApiSpec) ([]group, error) {
|
|||||||
for _, g := range api.Service.Groups {
|
for _, g := range api.Service.Groups {
|
||||||
var groupedRoutes group
|
var groupedRoutes group
|
||||||
for _, r := range g.Routes {
|
for _, r := range g.Routes {
|
||||||
handler, ok := apiutil.GetAnnotationValue(r.Annotations, "server", "handler")
|
handler := getHandlerName(r)
|
||||||
if !ok {
|
handler = handler + "(serverCtx)"
|
||||||
return nil, fmt.Errorf("missing handler annotation for route %q", r.Path)
|
|
||||||
}
|
|
||||||
handler = getHandlerBaseName(handler) + "Handler(serverCtx)"
|
|
||||||
folder, ok := apiutil.GetAnnotationValue(r.Annotations, "server", groupProperty)
|
folder, ok := apiutil.GetAnnotationValue(r.Annotations, "server", groupProperty)
|
||||||
if ok {
|
if ok {
|
||||||
handler = toPrefix(folder) + "." + strings.ToUpper(handler[:1]) + handler[1:]
|
handler = toPrefix(folder) + "." + strings.ToUpper(handler[:1]) + handler[1:]
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
"github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
contextFilename = "servicecontext.go"
|
contextFilename = "service_context"
|
||||||
contextTemplate = `package svc
|
contextTemplate = `package svc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -35,8 +37,13 @@ func NewServiceContext(c {{.config}}) *ServiceContext {
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func genServiceContext(dir string, api *spec.ApiSpec) error {
|
func genServiceContext(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
fp, created, err := util.MaybeCreateFile(dir, contextDir, contextFilename)
|
filename, err := format.FileNamingFormat(cfg.NamingFormat, contextFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fp, created, err := util.MaybeCreateFile(dir, contextDir, filename+".go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -64,10 +71,6 @@ func genServiceContext(dir string, api *spec.ApiSpec) error {
|
|||||||
var middlewareStr string
|
var middlewareStr string
|
||||||
var middlewareAssignment string
|
var middlewareAssignment string
|
||||||
var middlewares = getMiddleware(api)
|
var middlewares = getMiddleware(api)
|
||||||
err = genMiddleware(dir, middlewares)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range middlewares {
|
for _, item := range middlewares {
|
||||||
middlewareStr += fmt.Sprintf("%s rest.Middleware\n", item)
|
middlewareStr += fmt.Sprintf("%s rest.Middleware\n", item)
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import (
|
|||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
|
||||||
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typesFile = "types.go"
|
typesFile = "types"
|
||||||
typesTemplate = `// Code generated by goctl. DO NOT EDIT.
|
typesTemplate = `// Code generated by goctl. DO NOT EDIT.
|
||||||
package types{{if .containsTime}}
|
package types{{if .containsTime}}
|
||||||
import (
|
import (
|
||||||
@@ -43,19 +45,25 @@ func BuildTypes(types []spec.Type) (string, error) {
|
|||||||
return builder.String(), nil
|
return builder.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func genTypes(dir string, api *spec.ApiSpec) error {
|
func genTypes(dir string, cfg *config.Config, api *spec.ApiSpec) error {
|
||||||
val, err := BuildTypes(api.Types)
|
val, err := BuildTypes(api.Types)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := path.Join(dir, typesDir, typesFile)
|
typeFilename, err := format.FileNamingFormat(cfg.NamingFormat, typesFile)
|
||||||
os.Remove(filename)
|
|
||||||
|
|
||||||
fp, created, err := apiutil.MaybeCreateFile(dir, typesDir, typesFile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
typeFilename = typeFilename + ".go"
|
||||||
|
filename := path.Join(dir, typesDir, typeFilename)
|
||||||
|
os.Remove(filename)
|
||||||
|
|
||||||
|
fp, created, err := apiutil.MaybeCreateFile(dir, typesDir, typeFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !created {
|
if !created {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/gogen"
|
"github.com/tal-tech/go-zero/tools/goctl/api/gogen"
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@@ -60,6 +61,6 @@ func NewService(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gogen.DoGenProject(apiFilePath, abs)
|
err = gogen.DoGenProject(apiFilePath, abs, conf.DefaultFormat)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
122
tools/goctl/config/config.go
Normal file
122
tools/goctl/config/config.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
configFile = "config.yaml"
|
||||||
|
configFolder = "config"
|
||||||
|
DefaultFormat = "gozero"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultYaml = `# namingFormat is used to define the naming format of the generated file name.
|
||||||
|
# just like time formatting, you can specify the formatting style through the
|
||||||
|
# two format characters go, and zero. for example: snake format you can
|
||||||
|
# define as go_zero, camel case format you can it is defined as goZero,
|
||||||
|
# and even split characters can be specified, such as go#zero. in theory,
|
||||||
|
# any combination can be used, but the prerequisite must meet the naming conventions
|
||||||
|
# of each operating system file name. if you want to independently control the file
|
||||||
|
# naming style of the api, rpc, and model layers, you can set it through apiNamingFormat,
|
||||||
|
# rpcNamingFormat, modelNamingFormat, and independent control is not enabled by default.
|
||||||
|
# for more information, please see #{apiNamingFormat},#{rpcNamingFormat},#{modelNamingFormat}
|
||||||
|
# Note: namingFormat is based on snake or camel string
|
||||||
|
namingFormat: gozero
|
||||||
|
`
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
// NamingFormat is used to define the naming format of the generated file name.
|
||||||
|
// just like time formatting, you can specify the formatting style through the
|
||||||
|
// two format characters go, and zero. for example: snake format you can
|
||||||
|
// define as go_zero, camel case format you can it is defined as goZero,
|
||||||
|
// and even split characters can be specified, such as go#zero. in theory,
|
||||||
|
// any combination can be used, but the prerequisite must meet the naming conventions
|
||||||
|
// of each operating system file name.
|
||||||
|
// Note: NamingFormat is based on snake or camel string
|
||||||
|
NamingFormat string `yaml:"namingFormat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(format string) (*Config, error) {
|
||||||
|
if len(format) == 0 {
|
||||||
|
format = DefaultFormat
|
||||||
|
}
|
||||||
|
cfg := &Config{NamingFormat: format}
|
||||||
|
err := validate(cfg)
|
||||||
|
return cfg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitOrGetConfig() (*Config, error) {
|
||||||
|
var (
|
||||||
|
defaultConfig Config
|
||||||
|
)
|
||||||
|
err := yaml.Unmarshal([]byte(defaultYaml), &defaultConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
goctlHome, err := util.GetGoctlHome()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
configDir := filepath.Join(goctlHome, configFolder)
|
||||||
|
configFilename := filepath.Join(configDir, configFile)
|
||||||
|
if util.FileExists(configFilename) {
|
||||||
|
data, err := ioutil.ReadFile(configFilename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(data, &defaultConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate(&defaultConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &defaultConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = util.MkdirIfNotExist(configDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(configFilename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = f.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = f.WriteString(defaultYaml)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate(&defaultConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &defaultConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(cfg *Config) error {
|
||||||
|
if len(strings.TrimSpace(cfg.NamingFormat)) == 0 {
|
||||||
|
return errors.New("missing namingFormat")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
50
tools/goctl/config/readme.md
Normal file
50
tools/goctl/config/readme.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# 配置项管理
|
||||||
|
|
||||||
|
| 名称 | 是否可选 | 说明 |
|
||||||
|
|-------------------|----------|-----------------------------------------------|
|
||||||
|
| namingFormat | YES | 文件名称格式化符 |
|
||||||
|
|
||||||
|
# naming-format
|
||||||
|
`namingFormat`可以用于对生成代码的文件名称进行格式化,和日期格式化符(yyyy-MM-dd)类似,在代码生成时可以根据这些配置项的格式化符进行格式化。
|
||||||
|
|
||||||
|
## 格式化符(gozero)
|
||||||
|
格式化符有`go`,`zero`组成,如常见的三种格式化风格你可以这样编写:
|
||||||
|
* lower: `gozero`
|
||||||
|
* camel: `goZero`
|
||||||
|
* snake: `go_zero`
|
||||||
|
|
||||||
|
常见格式化符生成示例
|
||||||
|
源字符:welcome_to_go_zero
|
||||||
|
|
||||||
|
| 格式化符 | 格式化结果 | 说明 |
|
||||||
|
|------------|-----------------------|---------------------------|
|
||||||
|
| gozero | welcometogozero | 小写 |
|
||||||
|
| goZero | welcomeToGoZero | 驼峰 |
|
||||||
|
| go_zero | welcome_to_go_zero | snake |
|
||||||
|
| Go#zero | Welcome#to#go#zero | #号分割Title类型 |
|
||||||
|
| GOZERO | WELCOMETOGOZERO | 大写 |
|
||||||
|
| \_go#zero_ | \_welcome#to#go#zero_ | 下划线做前后缀,并且#分割 |
|
||||||
|
|
||||||
|
错误格式化符示例
|
||||||
|
* go
|
||||||
|
* gOZero
|
||||||
|
* zero
|
||||||
|
* goZEro
|
||||||
|
* goZERo
|
||||||
|
* goZeRo
|
||||||
|
* tal
|
||||||
|
|
||||||
|
# 使用方法
|
||||||
|
目前可通过在生成api、rpc、model时通过`--style`参数指定format格式,如:
|
||||||
|
```shell script
|
||||||
|
goctl api go test.api -dir . -style gozero
|
||||||
|
```
|
||||||
|
```shell script
|
||||||
|
goctl rpc proto -src test.proto -dir . -style go_zero
|
||||||
|
```
|
||||||
|
```shell script
|
||||||
|
goctl model mysql datasource -url="" -table="*" -dir ./snake -style GoZero
|
||||||
|
```
|
||||||
|
|
||||||
|
# 默认值
|
||||||
|
当不指定-style时默认值为`gozero`
|
||||||
@@ -18,6 +18,7 @@ ENV GOPROXY https://goproxy.cn,direct
|
|||||||
|
|
||||||
WORKDIR /build/zero
|
WORKDIR /build/zero
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN sh -c "[ -f go.mod ]" || exit
|
||||||
COPY {{.goRelPath}}/etc /app/etc
|
COPY {{.goRelPath}}/etc /app/etc
|
||||||
RUN go build -ldflags="-s -w" -o /app/{{.exeFile}} {{.goRelPath}}/{{.goFile}}
|
RUN go build -ldflags="-s -w" -o /app/{{.exeFile}} {{.goRelPath}}/{{.goFile}}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BuildVersion = "20201108"
|
BuildVersion = "20201125"
|
||||||
commands = []cli.Command{
|
commands = []cli.Command{
|
||||||
{
|
{
|
||||||
Name: "api",
|
Name: "api",
|
||||||
@@ -98,6 +98,11 @@ var (
|
|||||||
Name: "api",
|
Name: "api",
|
||||||
Usage: "the api file",
|
Usage: "the api file",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "style",
|
||||||
|
Required: false,
|
||||||
|
Usage: "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: gogen.GoCommand,
|
Action: gogen.GoCommand,
|
||||||
},
|
},
|
||||||
@@ -202,8 +207,9 @@ var (
|
|||||||
Usage: `generate rpc demo service`,
|
Usage: `generate rpc demo service`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "style",
|
Name: "style",
|
||||||
Usage: "the file naming style, lower|camel|snake,default is lower",
|
Required: false,
|
||||||
|
Usage: "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "idea",
|
Name: "idea",
|
||||||
@@ -240,8 +246,9 @@ var (
|
|||||||
Usage: `the target path of the code`,
|
Usage: `the target path of the code`,
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "style",
|
Name: "style",
|
||||||
Usage: "the file naming style, lower|camel|snake,default is lower",
|
Required: false,
|
||||||
|
Usage: "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "idea",
|
Name: "idea",
|
||||||
@@ -273,8 +280,9 @@ var (
|
|||||||
Usage: "the target dir",
|
Usage: "the target dir",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "style",
|
Name: "style",
|
||||||
Usage: "the file naming style, lower|camel|snake,default is lower",
|
Required: false,
|
||||||
|
Usage: "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "cache, c",
|
Name: "cache, c",
|
||||||
@@ -308,8 +316,9 @@ var (
|
|||||||
Usage: "the target dir",
|
Usage: "the target dir",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "style",
|
Name: "style",
|
||||||
Usage: "the file naming style, lower|camel|snake, default is lower",
|
Required: false,
|
||||||
|
Usage: "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "idea",
|
Name: "idea",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
* 通过ddl生成
|
* 通过ddl生成
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c=true
|
goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c
|
||||||
```
|
```
|
||||||
|
|
||||||
执行上述命令后即可快速生成CURD代码。
|
执行上述命令后即可快速生成CURD代码。
|
||||||
@@ -29,156 +29,191 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
```go
|
```go
|
||||||
|
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/core/stores/cache"
|
||||||
|
"github.com/tal-tech/go-zero/core/stores/sqlc"
|
||||||
|
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/tal-tech/go-zero/core/stringx"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
userFieldNames = builderx.FieldNames(&User{})
|
||||||
|
userRows = strings.Join(userFieldNames, ",")
|
||||||
|
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
|
||||||
|
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
|
||||||
|
|
||||||
|
cacheUserPrefix = "cache#User#user#"
|
||||||
|
cacheUserNamePrefix = "cache#User#name#"
|
||||||
|
cacheUserMobilePrefix = "cache#User#mobile#"
|
||||||
|
cacheUserIdPrefix = "cache#User#id#"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
UserModel interface {
|
||||||
|
Insert(data User) (sql.Result, error)
|
||||||
|
FindOne(id int64) (*User, error)
|
||||||
|
FindOneByUser(user string) (*User, error)
|
||||||
|
FindOneByName(name string) (*User, error)
|
||||||
|
FindOneByMobile(mobile string) (*User, error)
|
||||||
|
Update(data User) error
|
||||||
|
Delete(id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultUserModel struct {
|
||||||
|
sqlc.CachedConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
User struct {
|
||||||
|
Id int64 `db:"id"`
|
||||||
|
User string `db:"user"` // 用户
|
||||||
|
Name string `db:"name"` // 用户名称
|
||||||
|
Password string `db:"password"` // 用户密码
|
||||||
|
Mobile string `db:"mobile"` // 手机号
|
||||||
|
Gender string `db:"gender"` // 男|女|未公开
|
||||||
|
Nickname string `db:"nickname"` // 用户昵称
|
||||||
|
CreateTime time.Time `db:"create_time"`
|
||||||
|
UpdateTime time.Time `db:"update_time"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel {
|
||||||
|
return &defaultUserModel{
|
||||||
|
CachedConn: sqlc.NewConn(conn, c),
|
||||||
|
table: "user",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) Insert(data User) (sql.Result, error) {
|
||||||
|
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
|
||||||
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
||||||
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
||||||
|
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
|
||||||
|
return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
|
||||||
|
}, userMobileKey, userKey, userNameKey)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) FindOne(id int64) (*User, error) {
|
||||||
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
||||||
|
var resp User
|
||||||
|
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
|
||||||
|
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
||||||
|
return conn.QueryRow(v, query, id)
|
||||||
|
})
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) FindOneByUser(user string) (*User, error) {
|
||||||
|
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, user)
|
||||||
|
var resp User
|
||||||
|
err := m.QueryRowIndex(&resp, userKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where user = ? limit 1", userRows, m.table)
|
||||||
|
if err := conn.QueryRow(&resp, query, user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Id, nil
|
||||||
|
}, m.queryPrimary)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) FindOneByName(name string) (*User, error) {
|
||||||
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
|
||||||
|
var resp User
|
||||||
|
err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
|
||||||
|
if err := conn.QueryRow(&resp, query, name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Id, nil
|
||||||
|
}, m.queryPrimary)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) FindOneByMobile(mobile string) (*User, error) {
|
||||||
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
|
||||||
|
var resp User
|
||||||
|
err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
|
||||||
|
if err := conn.QueryRow(&resp, query, mobile); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Id, nil
|
||||||
|
}, m.queryPrimary)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) Update(data User) error {
|
||||||
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
|
||||||
|
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
|
query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
|
||||||
|
return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
|
||||||
|
}, userIdKey)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) Delete(id int64) error {
|
||||||
|
data, err := m.FindOne(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
||||||
|
userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
|
||||||
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
||||||
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
||||||
|
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
|
query := fmt.Sprintf("delete from %s where id = ?", m.table)
|
||||||
|
return conn.Exec(query, id)
|
||||||
|
}, userIdKey, userKey, userNameKey, userMobileKey)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) formatPrimary(primary interface{}) string {
|
||||||
|
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultUserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
|
||||||
|
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
||||||
|
return conn.QueryRow(v, query, primary)
|
||||||
|
}
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/core/stores/cache"
|
|
||||||
"github.com/tal-tech/go-zero/core/stores/sqlc"
|
|
||||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
|
||||||
"github.com/tal-tech/go-zero/core/stringx"
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
userFieldNames = builderx.FieldNames(&User{})
|
|
||||||
userRows = strings.Join(userFieldNames, ",")
|
|
||||||
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
|
|
||||||
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
|
|
||||||
|
|
||||||
cacheUserIdPrefix = "cache#User#id#"
|
|
||||||
cacheUserNamePrefix = "cache#User#name#"
|
|
||||||
cacheUserMobilePrefix = "cache#User#mobile#"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
UserModel struct {
|
|
||||||
sqlc.CachedConn
|
|
||||||
table string
|
|
||||||
}
|
|
||||||
|
|
||||||
User struct {
|
|
||||||
Id int64 `db:"id"`
|
|
||||||
Name string `db:"name"` // 用户名称
|
|
||||||
Password string `db:"password"` // 用户密码
|
|
||||||
Mobile string `db:"mobile"` // 手机号
|
|
||||||
Gender string `db:"gender"` // 男|女|未公开
|
|
||||||
Nickname string `db:"nickname"` // 用户昵称
|
|
||||||
CreateTime time.Time `db:"create_time"`
|
|
||||||
UpdateTime time.Time `db:"update_time"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) *UserModel {
|
|
||||||
return &UserModel{
|
|
||||||
CachedConn: sqlc.NewConn(conn, c),
|
|
||||||
table: "user",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Insert(data User) (sql.Result, error) {
|
|
||||||
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
|
||||||
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
|
||||||
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
|
||||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
|
|
||||||
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
|
|
||||||
}, userNameKey, userMobileKey)
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) FindOne(id int64) (*User, error) {
|
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
|
||||||
var resp User
|
|
||||||
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
|
|
||||||
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
|
||||||
return conn.QueryRow(v, query, id)
|
|
||||||
})
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
return &resp, nil
|
|
||||||
case sqlc.ErrNotFound:
|
|
||||||
return nil, ErrNotFound
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) FindOneByName(name string) (*User, error) {
|
|
||||||
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
|
|
||||||
var resp User
|
|
||||||
err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
|
||||||
query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
|
|
||||||
if err := conn.QueryRow(&resp, query, name); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resp.Id, nil
|
|
||||||
}, m.queryPrimary)
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
return &resp, nil
|
|
||||||
case sqlc.ErrNotFound:
|
|
||||||
return nil, ErrNotFound
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) FindOneByMobile(mobile string) (*User, error) {
|
|
||||||
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
|
|
||||||
var resp User
|
|
||||||
err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
|
||||||
query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
|
|
||||||
if err := conn.QueryRow(&resp, query, mobile); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resp.Id, nil
|
|
||||||
}, m.queryPrimary)
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
return &resp, nil
|
|
||||||
case sqlc.ErrNotFound:
|
|
||||||
return nil, ErrNotFound
|
|
||||||
default:
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Update(data User) error {
|
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
|
|
||||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
|
||||||
query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
|
|
||||||
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
|
|
||||||
}, userIdKey)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Delete(id int64) error {
|
|
||||||
data, err := m.FindOne(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
|
||||||
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
|
||||||
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
|
||||||
query := fmt.Sprintf("delete from %s where id = ?", m.table)
|
|
||||||
return conn.Exec(query, id)
|
|
||||||
}, userMobileKey, userIdKey, userNameKey)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) formatPrimary(primary interface{}) string {
|
|
||||||
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
|
|
||||||
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
|
||||||
return conn.QueryRow(v, query, primary)
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
@@ -211,25 +246,24 @@ OPTIONS:
|
|||||||
* ddl
|
* ddl
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
goctl model mysql -src={patterns} -dir={dir} -cache=true
|
goctl model mysql -src={patterns} -dir={dir} -cache
|
||||||
```
|
```
|
||||||
|
|
||||||
help
|
help
|
||||||
|
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
goctl model mysql ddl - generate mysql model from ddl
|
goctl model mysql ddl - generate mysql model from ddl
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
goctl model mysql ddl [command options] [arguments...]
|
goctl model mysql ddl [command options] [arguments...]
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
--src value, -s value the path or path globbing patterns of the ddl
|
--src value, -s value the path or path globbing patterns of the ddl
|
||||||
--dir value, -d value the target dir
|
--dir value, -d value the target dir
|
||||||
--style value the file naming style, lower|camel|underline,default is lower
|
--style value the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
|
||||||
--cache, -c generate code with cache [optional]
|
--cache, -c generate code with cache [optional]
|
||||||
--idea for idea plugin [optional]
|
--idea for idea plugin [optional]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* datasource
|
* datasource
|
||||||
@@ -242,18 +276,19 @@ OPTIONS:
|
|||||||
|
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
goctl model mysql datasource - generate model from datasource
|
goctl model mysql datasource - generate model from datasource
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
goctl model mysql datasource [command options] [arguments...]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
|
||||||
|
--table value, -t value the table or table globbing patterns in the database
|
||||||
|
--cache, -c generate code with cache [optional]
|
||||||
|
--dir value, -d value the target dir
|
||||||
|
--style value the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
|
||||||
|
--idea for idea plugin [optional]
|
||||||
|
|
||||||
USAGE:
|
|
||||||
goctl model mysql datasource [command options] [arguments...]
|
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
|
|
||||||
--table value, -t value the table or table globbing patterns in the database
|
|
||||||
--cache, -c generate code with cache [optional]
|
|
||||||
--dir value, -d value the target dir
|
|
||||||
--style value the file naming style, lower|camel|snake, default is lower
|
|
||||||
--idea for idea plugin [optional]
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -281,13 +316,13 @@ OPTIONS:
|
|||||||
* ddl
|
* ddl
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
goctl model -src={patterns} -dir={dir} -cache=false
|
goctl model -src={patterns} -dir={dir}
|
||||||
```
|
```
|
||||||
|
|
||||||
* datasource
|
* datasource
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
goctl model mysql datasource -url={datasource} -table={patterns} -dir={dir} -cache=false
|
goctl model mysql datasource -url={datasource} -table={patterns} -dir={dir}
|
||||||
```
|
```
|
||||||
|
|
||||||
生成代码仅基本的CURD结构。
|
生成代码仅基本的CURD结构。
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -10,6 +9,7 @@ import (
|
|||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
"github.com/tal-tech/go-zero/core/logx"
|
"github.com/tal-tech/go-zero/core/logx"
|
||||||
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
"github.com/tal-tech/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
|
||||||
@@ -24,9 +24,9 @@ const (
|
|||||||
flagDir = "dir"
|
flagDir = "dir"
|
||||||
flagCache = "cache"
|
flagCache = "cache"
|
||||||
flagIdea = "idea"
|
flagIdea = "idea"
|
||||||
flagStyle = "style"
|
|
||||||
flagUrl = "url"
|
flagUrl = "url"
|
||||||
flagTable = "table"
|
flagTable = "table"
|
||||||
|
flagStyle = "style"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MysqlDDL(ctx *cli.Context) error {
|
func MysqlDDL(ctx *cli.Context) error {
|
||||||
@@ -34,8 +34,12 @@ func MysqlDDL(ctx *cli.Context) error {
|
|||||||
dir := ctx.String(flagDir)
|
dir := ctx.String(flagDir)
|
||||||
cache := ctx.Bool(flagCache)
|
cache := ctx.Bool(flagCache)
|
||||||
idea := ctx.Bool(flagIdea)
|
idea := ctx.Bool(flagIdea)
|
||||||
namingStyle := strings.TrimSpace(ctx.String(flagStyle))
|
style := ctx.String(flagStyle)
|
||||||
return fromDDl(src, dir, namingStyle, cache, idea)
|
cfg, err := config.NewConfig(style)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fromDDl(src, dir, cfg, cache, idea)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MyDataSource(ctx *cli.Context) error {
|
func MyDataSource(ctx *cli.Context) error {
|
||||||
@@ -43,26 +47,23 @@ func MyDataSource(ctx *cli.Context) error {
|
|||||||
dir := strings.TrimSpace(ctx.String(flagDir))
|
dir := strings.TrimSpace(ctx.String(flagDir))
|
||||||
cache := ctx.Bool(flagCache)
|
cache := ctx.Bool(flagCache)
|
||||||
idea := ctx.Bool(flagIdea)
|
idea := ctx.Bool(flagIdea)
|
||||||
namingStyle := strings.TrimSpace(ctx.String(flagStyle))
|
style := ctx.String(flagStyle)
|
||||||
pattern := strings.TrimSpace(ctx.String(flagTable))
|
pattern := strings.TrimSpace(ctx.String(flagTable))
|
||||||
return fromDataSource(url, pattern, dir, namingStyle, cache, idea)
|
cfg, err := config.NewConfig(style)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromDataSource(url, pattern, dir, cfg, cache, idea)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
|
func fromDDl(src, dir string, cfg *config.Config, cache, idea bool) error {
|
||||||
log := console.NewConsole(idea)
|
log := console.NewConsole(idea)
|
||||||
src = strings.TrimSpace(src)
|
src = strings.TrimSpace(src)
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return errors.New("expected path or path globbing patterns, but nothing found")
|
return errors.New("expected path or path globbing patterns, but nothing found")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch namingStyle {
|
|
||||||
case gen.NamingLower, gen.NamingCamel, gen.NamingSnake:
|
|
||||||
case "":
|
|
||||||
namingStyle = gen.NamingLower
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unexpected naming style: %s", namingStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := util.MatchFiles(src)
|
files, err := util.MatchFiles(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -81,7 +82,7 @@ func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
|
|||||||
|
|
||||||
source = append(source, string(data))
|
source = append(source, string(data))
|
||||||
}
|
}
|
||||||
generator, err := gen.NewDefaultGenerator(dir, namingStyle, gen.WithConsoleOption(log))
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) error {
|
func fromDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
|
||||||
log := console.NewConsole(idea)
|
log := console.NewConsole(idea)
|
||||||
if len(url) == 0 {
|
if len(url) == 0 {
|
||||||
log.Error("%v", "expected data source of mysql, but nothing found")
|
log.Error("%v", "expected data source of mysql, but nothing found")
|
||||||
@@ -102,25 +103,17 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch namingStyle {
|
dsn, err := mysql.ParseDSN(url)
|
||||||
case gen.NamingLower, gen.NamingCamel, gen.NamingSnake:
|
|
||||||
case "":
|
|
||||||
namingStyle = gen.NamingLower
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unexpected naming style: %s", namingStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := mysql.ParseDSN(url)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logx.Disable()
|
logx.Disable()
|
||||||
databaseSource := strings.TrimSuffix(url, "/"+cfg.DBName) + "/information_schema"
|
databaseSource := strings.TrimSuffix(url, "/"+dsn.DBName) + "/information_schema"
|
||||||
db := sqlx.NewMysql(databaseSource)
|
db := sqlx.NewMysql(databaseSource)
|
||||||
im := model.NewInformationSchemaModel(db)
|
im := model.NewInformationSchemaModel(db)
|
||||||
|
|
||||||
tables, err := im.GetAllTables(cfg.DBName)
|
tables, err := im.GetAllTables(dsn.DBName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -135,7 +128,7 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
|
|||||||
if !match {
|
if !match {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
columns, err := im.FindByTableName(cfg.DBName, item)
|
columns, err := im.FindByTableName(dsn.DBName, item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -146,11 +139,11 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
|
|||||||
return errors.New("no tables matched")
|
return errors.New("no tables matched")
|
||||||
}
|
}
|
||||||
|
|
||||||
generator, err := gen.NewDefaultGenerator(dir, namingStyle, gen.WithConsoleOption(log))
|
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = generator.StartFromInformationSchema(cfg.DBName, matchTables, cache)
|
err = generator.StartFromInformationSchema(dsn.DBName, matchTables, cache)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,22 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sql = "-- 用户表 --\nCREATE TABLE `user` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n UNIQUE KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;\n\n"
|
var sql = "-- 用户表 --\nCREATE TABLE `user` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n UNIQUE KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;\n\n"
|
||||||
|
var cfg = &config.Config{
|
||||||
|
NamingFormat: "gozero",
|
||||||
|
}
|
||||||
|
|
||||||
func TestFromDDl(t *testing.T) {
|
func TestFromDDl(t *testing.T) {
|
||||||
err := fromDDl("./user.sql", t.TempDir(), gen.NamingCamel, true, false)
|
err := fromDDl("./user.sql", t.TempDir(), cfg, true, false)
|
||||||
assert.Equal(t, errNotMatched, err)
|
assert.Equal(t, errNotMatched, err)
|
||||||
|
|
||||||
// case dir is not exists
|
// case dir is not exists
|
||||||
unknownDir := filepath.Join(t.TempDir(), "test", "user.sql")
|
unknownDir := filepath.Join(t.TempDir(), "test", "user.sql")
|
||||||
err = fromDDl(unknownDir, t.TempDir(), gen.NamingCamel, true, false)
|
err = fromDDl(unknownDir, t.TempDir(), cfg, true, false)
|
||||||
assert.True(t, func() bool {
|
assert.True(t, func() bool {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case *os.PathError:
|
case *os.PathError:
|
||||||
@@ -30,18 +33,11 @@ func TestFromDDl(t *testing.T) {
|
|||||||
}())
|
}())
|
||||||
|
|
||||||
// case empty src
|
// case empty src
|
||||||
err = fromDDl("", t.TempDir(), gen.NamingCamel, true, false)
|
err = fromDDl("", t.TempDir(), cfg, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.Equal(t, "expected path or path globbing patterns, but nothing found", err.Error())
|
assert.Equal(t, "expected path or path globbing patterns, but nothing found", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// case unknown naming style
|
|
||||||
tmp := filepath.Join(t.TempDir(), "user.sql")
|
|
||||||
err = fromDDl(tmp, t.TempDir(), "lower1", true, false)
|
|
||||||
if err != nil {
|
|
||||||
assert.Equal(t, "unexpected naming style: lower1", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDir := filepath.Join(t.TempDir(), "test")
|
tempDir := filepath.Join(t.TempDir(), "test")
|
||||||
err = util.MkdirIfNotExist(tempDir)
|
err = util.MkdirIfNotExist(tempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -67,7 +63,7 @@ func TestFromDDl(t *testing.T) {
|
|||||||
_, err = os.Stat(user2Sql)
|
_, err = os.Stat(user2Sql)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = fromDDl(filepath.Join(tempDir, "user*.sql"), tempDir, gen.NamingLower, true, false)
|
err = fromDDl(filepath.Join(tempDir, "user*.sql"), tempDir, cfg, true, false)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
_, err = os.Stat(filepath.Join(tempDir, "usermodel.go"))
|
_, err = os.Stat(filepath.Join(tempDir, "usermodel.go"))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# generate model with cache from ddl
|
# generate model with cache from ddl
|
||||||
fromDDL:
|
fromDDL:
|
||||||
goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -c
|
goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -cache
|
||||||
|
|
||||||
|
|
||||||
# generate model with cache from data source
|
# generate model with cache from data source
|
||||||
@@ -12,4 +12,4 @@ datasource=127.0.0.1:3306
|
|||||||
database=gozero
|
database=gozero
|
||||||
|
|
||||||
fromDataSource:
|
fromDataSource:
|
||||||
goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style camel
|
goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style gozero
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
-- 用户表 --
|
-- 用户表 --
|
||||||
CREATE TABLE `user` (
|
CREATE TABLE `user` (
|
||||||
`id` bigint(10) NOT NULL AUTO_INCREMENT,
|
`id` bigint(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user` varchar(50) NOT NULL DEFAULT '' COMMENT '用户',
|
||||||
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
|
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
|
||||||
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
|
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
|
||||||
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
|
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
|
||||||
@@ -10,6 +11,7 @@ CREATE TABLE `user` (
|
|||||||
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `name_index` (`name`),
|
UNIQUE KEY `name_index` (`name`),
|
||||||
|
UNIQUE KEY `user_index` (`user`),
|
||||||
UNIQUE KEY `mobile_index` (`mobile`)
|
UNIQUE KEY `mobile_index` (`mobile`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genDelete(table Table, withCache bool) (string, error) {
|
func genDelete(table Table, withCache bool) (string, string, error) {
|
||||||
keySet := collection.NewSet()
|
keySet := collection.NewSet()
|
||||||
keyVariableSet := collection.NewSet()
|
keyVariableSet := collection.NewSet()
|
||||||
for fieldName, key := range table.CacheKey {
|
for fieldName, key := range table.CacheKey {
|
||||||
@@ -24,7 +24,7 @@ func genDelete(table Table, withCache bool) (string, error) {
|
|||||||
camel := table.Name.ToCamel()
|
camel := table.Name.ToCamel()
|
||||||
text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
|
text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := util.With("delete").
|
output, err := util.With("delete").
|
||||||
@@ -40,8 +40,23 @@ func genDelete(table Table, withCache bool) (string, error) {
|
|||||||
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
|
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), nil
|
// interface method
|
||||||
|
text, err = util.LoadTemplate(category, deleteMethodTemplateFile, template.DeleteMethod)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteMethodOut, err := util.With("deleteMethod").
|
||||||
|
Parse(text).
|
||||||
|
Execute(map[string]interface{}{
|
||||||
|
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
|
||||||
|
"dataType": table.PrimaryKey.DataType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return output.String(), deleteMethodOut.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genFindOne(table Table, withCache bool) (string, error) {
|
func genFindOne(table Table, withCache bool) (string, string, error) {
|
||||||
camel := table.Name.ToCamel()
|
camel := table.Name.ToCamel()
|
||||||
text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
|
text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := util.With("findOne").
|
output, err := util.With("findOne").
|
||||||
@@ -26,8 +26,23 @@ func genFindOne(table Table, withCache bool) (string, error) {
|
|||||||
"cacheKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
|
"cacheKeyVariable": table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), nil
|
text, err = util.LoadTemplate(category, findOneMethodTemplateFile, template.FindOneMethod)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
findOneMethod, err := util.With("findOneMethod").
|
||||||
|
Parse(text).
|
||||||
|
Execute(map[string]interface{}{
|
||||||
|
"upperStartCamelObject": camel,
|
||||||
|
"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
|
||||||
|
"dataType": table.PrimaryKey.DataType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return output.String(), findOneMethod.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,16 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
type findOneCode struct {
|
||||||
|
findOneMethod string
|
||||||
|
findOneInterfaceMethod string
|
||||||
|
cacheExtra string
|
||||||
|
}
|
||||||
|
|
||||||
|
func genFindOneByField(table Table, withCache bool) (*findOneCode, error) {
|
||||||
text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
|
text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t := util.With("findOneByField").Parse(text)
|
t := util.With("findOneByField").Parse(text)
|
||||||
@@ -36,15 +42,40 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
|||||||
"originalField": field.Name.Source(),
|
"originalField": field.Name.Source(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
list = append(list, output.String())
|
list = append(list, output.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text, err = util.LoadTemplate(category, findOneByFieldMethodTemplateFile, template.FindOneByFieldMethod)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t = util.With("findOneByFieldMethod").Parse(text)
|
||||||
|
var listMethod []string
|
||||||
|
for _, field := range table.Fields {
|
||||||
|
if field.IsPrimaryKey || !field.IsUniqueKey {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
camelFieldName := field.Name.ToCamel()
|
||||||
|
output, err := t.Execute(map[string]interface{}{
|
||||||
|
"upperStartCamelObject": camelTableName,
|
||||||
|
"upperField": camelFieldName,
|
||||||
|
"in": fmt.Sprintf("%s %s", stringx.From(camelFieldName).UnTitle(), field.DataType),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
listMethod = append(listMethod, output.String())
|
||||||
|
}
|
||||||
|
|
||||||
if withCache {
|
if withCache {
|
||||||
text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
|
text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
|
out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
|
||||||
@@ -54,11 +85,18 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
|
|||||||
"originalPrimaryField": table.PrimaryKey.Name.Source(),
|
"originalPrimaryField": table.PrimaryKey.Name.Source(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(list, "\n"), out.String(), nil
|
return &findOneCode{
|
||||||
|
findOneMethod: strings.Join(list, util.NL),
|
||||||
|
findOneInterfaceMethod: strings.Join(listMethod, util.NL),
|
||||||
|
cacheExtra: out.String(),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
return strings.Join(list, "\n"), "", nil
|
|
||||||
|
|
||||||
|
return &findOneCode{
|
||||||
|
findOneMethod: strings.Join(list, util.NL),
|
||||||
|
findOneInterfaceMethod: strings.Join(listMethod, util.NL),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
|
||||||
|
modelutil "github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,13 +31,13 @@ type (
|
|||||||
//source string
|
//source string
|
||||||
dir string
|
dir string
|
||||||
console.Console
|
console.Console
|
||||||
pkg string
|
pkg string
|
||||||
namingStyle string
|
cfg *config.Config
|
||||||
}
|
}
|
||||||
Option func(generator *defaultGenerator)
|
Option func(generator *defaultGenerator)
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDefaultGenerator(dir, namingStyle string, opt ...Option) (*defaultGenerator, error) {
|
func NewDefaultGenerator(dir string, cfg *config.Config, opt ...Option) (*defaultGenerator, error) {
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
dir = pwd
|
dir = pwd
|
||||||
}
|
}
|
||||||
@@ -50,7 +53,7 @@ func NewDefaultGenerator(dir, namingStyle string, opt ...Option) (*defaultGenera
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
generator := &defaultGenerator{dir: dir, namingStyle: namingStyle, pkg: pkg}
|
generator := &defaultGenerator{dir: dir, cfg: cfg, pkg: pkg}
|
||||||
var optionList []Option
|
var optionList []Option
|
||||||
optionList = append(optionList, newDefaultOption())
|
optionList = append(optionList, newDefaultOption())
|
||||||
optionList = append(optionList, opt...)
|
optionList = append(optionList, opt...)
|
||||||
@@ -114,13 +117,12 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
|
|||||||
|
|
||||||
for tableName, code := range modelList {
|
for tableName, code := range modelList {
|
||||||
tn := stringx.From(tableName)
|
tn := stringx.From(tableName)
|
||||||
name := fmt.Sprintf("%smodel.go", strings.ToLower(tn.ToCamel()))
|
modelFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, fmt.Sprintf("%s_model", tn.Source()))
|
||||||
switch g.namingStyle {
|
if err != nil {
|
||||||
case NamingCamel:
|
return err
|
||||||
name = fmt.Sprintf("%sModel.go", tn.ToCamel())
|
|
||||||
case NamingSnake:
|
|
||||||
name = fmt.Sprintf("%s_model.go", tn.ToSnake())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := modelFilename + ".go"
|
||||||
filename := filepath.Join(dirAbs, name)
|
filename := filepath.Join(dirAbs, name)
|
||||||
if util.FileExists(filename) {
|
if util.FileExists(filename) {
|
||||||
g.Warning("%s already exists, ignored.", name)
|
g.Warning("%s already exists, ignored.", name)
|
||||||
@@ -132,10 +134,12 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate error file
|
// generate error file
|
||||||
filename := filepath.Join(dirAbs, "vars.go")
|
varFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, "vars")
|
||||||
if g.namingStyle == NamingCamel {
|
if err != nil {
|
||||||
filename = filepath.Join(dirAbs, "Vars.go")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join(dirAbs, varFilename+".go")
|
||||||
text, err := util.LoadTemplate(category, errTemplateFile, template.Error)
|
text, err := util.LoadTemplate(category, errTemplateFile, template.Error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -219,39 +223,41 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
typesCode, err := genTypes(table, withCache)
|
insertCode, insertCodeMethod, err := genInsert(table, withCache)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
newCode, err := genNew(table, withCache)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
insertCode, err := genInsert(table, withCache)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var findCode = make([]string, 0)
|
var findCode = make([]string, 0)
|
||||||
findOneCode, err := genFindOne(table, withCache)
|
findOneCode, findOneCodeMethod, err := genFindOne(table, withCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
findOneByFieldCode, extraMethod, err := genFindOneByField(table, withCache)
|
ret, err := genFindOneByField(table, withCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
findCode = append(findCode, findOneCode, findOneByFieldCode)
|
findCode = append(findCode, findOneCode, ret.findOneMethod)
|
||||||
updateCode, err := genUpdate(table, withCache)
|
updateCode, updateCodeMethod, err := genUpdate(table, withCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteCode, err := genDelete(table, withCache)
|
deleteCode, deleteCodeMethod, err := genDelete(table, withCache)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var list []string
|
||||||
|
list = append(list, insertCodeMethod, findOneCodeMethod, ret.findOneInterfaceMethod, updateCodeMethod, deleteCodeMethod)
|
||||||
|
typesCode, err := genTypes(table, strings.Join(modelutil.TrimStringSlice(list), util.NL), withCache)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
newCode, err := genNew(table, withCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -266,7 +272,7 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
|
|||||||
"find": strings.Join(findCode, "\n"),
|
"find": strings.Join(findCode, "\n"),
|
||||||
"update": updateCode,
|
"update": updateCode,
|
||||||
"delete": deleteCode,
|
"delete": deleteCode,
|
||||||
"extraMethod": extraMethod,
|
"extraMethod": ret.cacheExtra,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/tal-tech/go-zero/core/logx"
|
"github.com/tal-tech/go-zero/core/logx"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -22,7 +23,9 @@ func TestCacheModel(t *testing.T) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
_ = os.RemoveAll(dir)
|
_ = os.RemoveAll(dir)
|
||||||
}()
|
}()
|
||||||
g, err := NewDefaultGenerator(cacheDir, NamingCamel)
|
g, err := NewDefaultGenerator(cacheDir, &config.Config{
|
||||||
|
NamingFormat: "GoZero",
|
||||||
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = g.StartFromDDL(source, true)
|
err = g.StartFromDDL(source, true)
|
||||||
@@ -31,7 +34,9 @@ func TestCacheModel(t *testing.T) {
|
|||||||
_, err := os.Stat(filepath.Join(cacheDir, "TestUserInfoModel.go"))
|
_, err := os.Stat(filepath.Join(cacheDir, "TestUserInfoModel.go"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}())
|
}())
|
||||||
g, err = NewDefaultGenerator(noCacheDir, NamingLower)
|
g, err = NewDefaultGenerator(noCacheDir, &config.Config{
|
||||||
|
NamingFormat: "gozero",
|
||||||
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = g.StartFromDDL(source, false)
|
err = g.StartFromDDL(source, false)
|
||||||
@@ -51,7 +56,9 @@ func TestNamingModel(t *testing.T) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
_ = os.RemoveAll(dir)
|
_ = os.RemoveAll(dir)
|
||||||
}()
|
}()
|
||||||
g, err := NewDefaultGenerator(camelDir, NamingCamel)
|
g, err := NewDefaultGenerator(camelDir, &config.Config{
|
||||||
|
NamingFormat: "GoZero",
|
||||||
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = g.StartFromDDL(source, true)
|
err = g.StartFromDDL(source, true)
|
||||||
@@ -60,7 +67,9 @@ func TestNamingModel(t *testing.T) {
|
|||||||
_, err := os.Stat(filepath.Join(camelDir, "TestUserInfoModel.go"))
|
_, err := os.Stat(filepath.Join(camelDir, "TestUserInfoModel.go"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}())
|
}())
|
||||||
g, err = NewDefaultGenerator(snakeDir, NamingSnake)
|
g, err = NewDefaultGenerator(snakeDir, &config.Config{
|
||||||
|
NamingFormat: "go_zero",
|
||||||
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = g.StartFromDDL(source, true)
|
err = g.StartFromDDL(source, true)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genInsert(table Table, withCache bool) (string, error) {
|
func genInsert(table Table, withCache bool) (string, string, error) {
|
||||||
keySet := collection.NewSet()
|
keySet := collection.NewSet()
|
||||||
keyVariableSet := collection.NewSet()
|
keyVariableSet := collection.NewSet()
|
||||||
for fieldName, key := range table.CacheKey {
|
for fieldName, key := range table.CacheKey {
|
||||||
@@ -36,7 +36,7 @@ func genInsert(table Table, withCache bool) (string, error) {
|
|||||||
camel := table.Name.ToCamel()
|
camel := table.Name.ToCamel()
|
||||||
text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
|
text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := util.With("insert").
|
output, err := util.With("insert").
|
||||||
@@ -52,8 +52,23 @@ func genInsert(table Table, withCache bool) (string, error) {
|
|||||||
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
|
"keyValues": strings.Join(keyVariableSet.KeysStr(), ", "),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), nil
|
// interface method
|
||||||
|
text, err = util.LoadTemplate(category, insertTemplateMethodFile, template.InsertMethod)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
insertMethodOutput, err := util.With("insertMethod").
|
||||||
|
Parse(text).
|
||||||
|
Execute(map[string]interface{}{
|
||||||
|
"upperStartCamelObject": camel,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.String(), insertMethodOutput.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package gen
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
@@ -33,8 +34,14 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
|
|||||||
camelFieldName := field.Name.ToCamel()
|
camelFieldName := field.Name.ToCamel()
|
||||||
lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
|
lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
|
||||||
left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
|
left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
|
||||||
|
if strings.ToLower(camelFieldName) == strings.ToLower(camelTableName) {
|
||||||
|
left = fmt.Sprintf("cache%sPrefix", camelTableName)
|
||||||
|
}
|
||||||
right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
|
right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
|
||||||
variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
|
variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
|
||||||
|
if strings.ToLower(lowerStartCamelTableName) == strings.ToLower(camelFieldName) {
|
||||||
|
variable = fmt.Sprintf("%sKey", lowerStartCamelTableName)
|
||||||
|
}
|
||||||
m[field.Name.Source()] = Key{
|
m[field.Name.Source()] = Key{
|
||||||
VarExpression: fmt.Sprintf(`%s = "%s"`, left, right),
|
VarExpression: fmt.Sprintf(`%s = "%s"`, left, right),
|
||||||
Left: left,
|
Left: left,
|
||||||
|
|||||||
@@ -11,31 +11,40 @@ import (
|
|||||||
const (
|
const (
|
||||||
category = "model"
|
category = "model"
|
||||||
deleteTemplateFile = "delete.tpl"
|
deleteTemplateFile = "delete.tpl"
|
||||||
|
deleteMethodTemplateFile = "interface-delete.tpl"
|
||||||
fieldTemplateFile = "filed.tpl"
|
fieldTemplateFile = "filed.tpl"
|
||||||
findOneTemplateFile = "find-one.tpl"
|
findOneTemplateFile = "find-one.tpl"
|
||||||
|
findOneMethodTemplateFile = "interface-find-one.tpl"
|
||||||
findOneByFieldTemplateFile = "find-one-by-field.tpl"
|
findOneByFieldTemplateFile = "find-one-by-field.tpl"
|
||||||
|
findOneByFieldMethodTemplateFile = "interface-find-one-by-field.tpl"
|
||||||
findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
|
findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
|
||||||
importsTemplateFile = "import.tpl"
|
importsTemplateFile = "import.tpl"
|
||||||
importsWithNoCacheTemplateFile = "import-no-cache.tpl"
|
importsWithNoCacheTemplateFile = "import-no-cache.tpl"
|
||||||
insertTemplateFile = "insert.tpl"
|
insertTemplateFile = "insert.tpl"
|
||||||
|
insertTemplateMethodFile = "interface-insert.tpl"
|
||||||
modelTemplateFile = "model.tpl"
|
modelTemplateFile = "model.tpl"
|
||||||
modelNewTemplateFile = "model-new.tpl"
|
modelNewTemplateFile = "model-new.tpl"
|
||||||
tagTemplateFile = "tag.tpl"
|
tagTemplateFile = "tag.tpl"
|
||||||
typesTemplateFile = "types.tpl"
|
typesTemplateFile = "types.tpl"
|
||||||
updateTemplateFile = "update.tpl"
|
updateTemplateFile = "update.tpl"
|
||||||
|
updateMethodTemplateFile = "interface-update.tpl"
|
||||||
varTemplateFile = "var.tpl"
|
varTemplateFile = "var.tpl"
|
||||||
errTemplateFile = "err.tpl"
|
errTemplateFile = "err.tpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
var templates = map[string]string{
|
var templates = map[string]string{
|
||||||
deleteTemplateFile: template.Delete,
|
deleteTemplateFile: template.Delete,
|
||||||
|
deleteMethodTemplateFile: template.DeleteMethod,
|
||||||
fieldTemplateFile: template.Field,
|
fieldTemplateFile: template.Field,
|
||||||
findOneTemplateFile: template.FindOne,
|
findOneTemplateFile: template.FindOne,
|
||||||
|
findOneMethodTemplateFile: template.FindOneMethod,
|
||||||
findOneByFieldTemplateFile: template.FindOneByField,
|
findOneByFieldTemplateFile: template.FindOneByField,
|
||||||
|
findOneByFieldMethodTemplateFile: template.FindOneByFieldMethod,
|
||||||
findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
|
findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
|
||||||
importsTemplateFile: template.Imports,
|
importsTemplateFile: template.Imports,
|
||||||
importsWithNoCacheTemplateFile: template.ImportsNoCache,
|
importsWithNoCacheTemplateFile: template.ImportsNoCache,
|
||||||
insertTemplateFile: template.Insert,
|
insertTemplateFile: template.Insert,
|
||||||
|
insertTemplateMethodFile: template.InsertMethod,
|
||||||
modelTemplateFile: template.Model,
|
modelTemplateFile: template.Model,
|
||||||
modelNewTemplateFile: template.New,
|
modelNewTemplateFile: template.New,
|
||||||
tagTemplateFile: template.Tag,
|
tagTemplateFile: template.Tag,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genTypes(table Table, withCache bool) (string, error) {
|
func genTypes(table Table, methods string, withCache bool) (string, error) {
|
||||||
fields := table.Fields
|
fields := table.Fields
|
||||||
fieldsString, err := genFields(fields)
|
fieldsString, err := genFields(fields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -21,6 +21,7 @@ func genTypes(table Table, withCache bool) (string, error) {
|
|||||||
Parse(text).
|
Parse(text).
|
||||||
Execute(map[string]interface{}{
|
Execute(map[string]interface{}{
|
||||||
"withCache": withCache,
|
"withCache": withCache,
|
||||||
|
"method": methods,
|
||||||
"upperStartCamelObject": table.Name.ToCamel(),
|
"upperStartCamelObject": table.Name.ToCamel(),
|
||||||
"fields": fieldsString,
|
"fields": fieldsString,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genUpdate(table Table, withCache bool) (string, error) {
|
func genUpdate(table Table, withCache bool) (string, string, error) {
|
||||||
expressionValues := make([]string, 0)
|
expressionValues := make([]string, 0)
|
||||||
for _, filed := range table.Fields {
|
for _, filed := range table.Fields {
|
||||||
camel := filed.Name.ToCamel()
|
camel := filed.Name.ToCamel()
|
||||||
@@ -24,7 +24,7 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
|||||||
camelTableName := table.Name.ToCamel()
|
camelTableName := table.Name.ToCamel()
|
||||||
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
|
text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := util.With("update").
|
output, err := util.With("update").
|
||||||
@@ -39,8 +39,23 @@ func genUpdate(table Table, withCache bool) (string, error) {
|
|||||||
"expressionValues": strings.Join(expressionValues, ", "),
|
"expressionValues": strings.Join(expressionValues, ", "),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String(), nil
|
// update interface method
|
||||||
|
text, err = util.LoadTemplate(category, updateMethodTemplateFile, template.UpdateMethod)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMethodOutput, err := util.With("updateMethod").
|
||||||
|
Parse(text).
|
||||||
|
Execute(map[string]interface{}{
|
||||||
|
"upperStartCamelObject": camelTableName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.String(), updateMethodOutput.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ func TestConvertColumn(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey)
|
assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey)
|
||||||
assert.Equal(t, "id", table.PrimaryKey.Name.Source())
|
assert.Equal(t, "id", table.PrimaryKey.Name.Source())
|
||||||
assert.Equal(t, "mobile", table.Fields[1].Name.Source())
|
for _, item := range table.Fields {
|
||||||
assert.True(t, table.Fields[1].IsUniqueKey)
|
if item.Name.Source() == "mobile" {
|
||||||
|
assert.True(t, item.IsUniqueKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
var Delete = `
|
var Delete = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
|
func (m *default{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
|
||||||
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
|
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
|
||||||
if err!=nil{
|
if err!=nil{
|
||||||
return err
|
return err
|
||||||
@@ -16,3 +16,5 @@ func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}}
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var DeleteMethod = `Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error`
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package template
|
|||||||
|
|
||||||
// 通过id查询
|
// 通过id查询
|
||||||
var FindOne = `
|
var FindOne = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
|
func (m *default{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
|
||||||
{{if .withCache}}{{.cacheKey}}
|
{{if .withCache}}{{.cacheKey}}
|
||||||
var resp {{.upperStartCamelObject}}
|
var resp {{.upperStartCamelObject}}
|
||||||
err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error {
|
err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error {
|
||||||
@@ -32,7 +32,7 @@ func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}}
|
|||||||
|
|
||||||
// 通过指定字段查询
|
// 通过指定字段查询
|
||||||
var FindOneByField = `
|
var FindOneByField = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) {
|
func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) {
|
||||||
{{if .withCache}}{{.cacheKey}}
|
{{if .withCache}}{{.cacheKey}}
|
||||||
var resp {{.upperStartCamelObject}}
|
var resp {{.upperStartCamelObject}}
|
||||||
err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
@@ -64,12 +64,15 @@ func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{
|
|||||||
}{{end}}
|
}{{end}}
|
||||||
`
|
`
|
||||||
var FindOneByFieldExtraMethod = `
|
var FindOneByFieldExtraMethod = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
|
func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
|
||||||
return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
|
return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
|
func (m *default{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
|
||||||
query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table )
|
query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table )
|
||||||
return conn.QueryRow(v, query, primary)
|
return conn.QueryRow(v, query, primary)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var FindOneMethod = `FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)`
|
||||||
|
var FindOneByFieldMethod = `FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) `
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
var Insert = `
|
var Insert = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
|
func (m *default{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
|
||||||
{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
|
{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
|
||||||
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
|
query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
|
||||||
@@ -13,3 +13,5 @@ func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}
|
|||||||
return ret,err
|
return ret,err
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var InsertMethod = `Insert(data {{.upperStartCamelObject}}) (sql.Result,error)`
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
var New = `
|
var New = `
|
||||||
func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) *{{.upperStartCamelObject}}Model {
|
func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model {
|
||||||
return &{{.upperStartCamelObject}}Model{
|
return &default{{.upperStartCamelObject}}Model{
|
||||||
{{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}},
|
{{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}},
|
||||||
table: "{{.table}}",
|
table: "{{.table}}",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ package template
|
|||||||
|
|
||||||
var Types = `
|
var Types = `
|
||||||
type (
|
type (
|
||||||
{{.upperStartCamelObject}}Model struct {
|
{{.upperStartCamelObject}}Model interface{
|
||||||
|
{{.method}}
|
||||||
|
}
|
||||||
|
|
||||||
|
default{{.upperStartCamelObject}}Model struct {
|
||||||
{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
|
{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
|
||||||
table string
|
table string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
var Update = `
|
var Update = `
|
||||||
func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
|
func (m *default{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
|
||||||
{{if .withCache}}{{.primaryCacheKey}}
|
{{if .withCache}}{{.primaryCacheKey}}
|
||||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
|
query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
|
||||||
@@ -11,3 +11,5 @@ func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var UpdateMethod = `Update(data {{.upperStartCamelObject}}) error`
|
||||||
|
|||||||
12
tools/goctl/model/sql/util/slice.go
Normal file
12
tools/goctl/model/sql/util/slice.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
func TrimStringSlice(list []string) []string {
|
||||||
|
var out []string
|
||||||
|
for _, item := range list {
|
||||||
|
if len(item) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, item)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -24,32 +24,26 @@ func Rpc(c *cli.Context) error {
|
|||||||
return errors.New("missing -dir")
|
return errors.New("missing -dir")
|
||||||
}
|
}
|
||||||
|
|
||||||
namingStyle, valid := generator.IsNamingValid(style)
|
g, err := generator.NewDefaultRpcGenerator(style)
|
||||||
if !valid {
|
if err != nil {
|
||||||
return fmt.Errorf("unexpected naming style %s", style)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
g := generator.NewDefaultRpcGenerator(namingStyle)
|
|
||||||
return g.Generate(src, out, protoImportPath)
|
return g.Generate(src, out, protoImportPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RpcNew is to generate rpc greet service, this greet service can speed
|
// RpcNew is to generate rpc greet service, this greet service can speed
|
||||||
// up your understanding of the zrpc service structure
|
// up your understanding of the zrpc service structure
|
||||||
func RpcNew(c *cli.Context) error {
|
func RpcNew(c *cli.Context) error {
|
||||||
name := c.Args().First()
|
rpcname := c.Args().First()
|
||||||
ext := filepath.Ext(name)
|
ext := filepath.Ext(rpcname)
|
||||||
if len(ext) > 0 {
|
if len(ext) > 0 {
|
||||||
return fmt.Errorf("unexpected ext: %s", ext)
|
return fmt.Errorf("unexpected ext: %s", ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
style := c.String("style")
|
style := c.String("style")
|
||||||
namingStyle, valid := generator.IsNamingValid(style)
|
|
||||||
if !valid {
|
|
||||||
return fmt.Errorf("expected naming style [lower|camel|snake], but found %s", style)
|
|
||||||
}
|
|
||||||
|
|
||||||
protoName := name + ".proto"
|
protoName := rpcname + ".proto"
|
||||||
filename := filepath.Join(".", name, protoName)
|
filename := filepath.Join(".", rpcname, protoName)
|
||||||
src, err := filepath.Abs(filename)
|
src, err := filepath.Abs(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -60,7 +54,11 @@ func RpcNew(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
g := generator.NewDefaultRpcGenerator(namingStyle)
|
g, err := generator.NewDefaultRpcGenerator(style)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return g.Generate(src, filepath.Dir(src), nil)
|
return g.Generate(src, filepath.Dir(src), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
|
||||||
)
|
|
||||||
|
|
||||||
func formatFilename(filename string, style NamingStyle) string {
|
|
||||||
switch style {
|
|
||||||
case namingCamel:
|
|
||||||
return stringx.From(filename).ToCamel()
|
|
||||||
case namingSnake:
|
|
||||||
return stringx.From(filename).ToSnake()
|
|
||||||
default:
|
|
||||||
return strings.ToLower(stringx.From(filename).ToCamel())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFormatFilename(t *testing.T) {
|
|
||||||
assert.Equal(t, "abc", formatFilename("a_b_c", namingLower))
|
|
||||||
assert.Equal(t, "ABC", formatFilename("a_b_c", namingCamel))
|
|
||||||
assert.Equal(t, "a_b_c", formatFilename("a_b_c", namingSnake))
|
|
||||||
assert.Equal(t, "a", formatFilename("a", namingSnake))
|
|
||||||
assert.Equal(t, "A", formatFilename("a", namingCamel))
|
|
||||||
// no flag to convert to snake
|
|
||||||
assert.Equal(t, "abc", formatFilename("abc", namingSnake))
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ package generator
|
|||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
"github.com/tal-tech/go-zero/tools/goctl/util/console"
|
||||||
@@ -10,18 +11,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RpcGenerator struct {
|
type RpcGenerator struct {
|
||||||
g Generator
|
g Generator
|
||||||
style NamingStyle
|
cfg *conf.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultRpcGenerator(style NamingStyle) *RpcGenerator {
|
func NewDefaultRpcGenerator(style string) (*RpcGenerator, error) {
|
||||||
return NewRpcGenerator(NewDefaultGenerator(), style)
|
cfg, err := conf.NewConfig(style)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewRpcGenerator(NewDefaultGenerator(), cfg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRpcGenerator(g Generator, style NamingStyle) *RpcGenerator {
|
func NewRpcGenerator(g Generator, cfg *conf.Config) *RpcGenerator {
|
||||||
return &RpcGenerator{
|
return &RpcGenerator{
|
||||||
g: g,
|
g: g,
|
||||||
style: style,
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,42 +62,42 @@ func (g *RpcGenerator) Generate(src, target string, protoImportPath []string) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenEtc(dirCtx, proto, g.style)
|
err = g.g.GenEtc(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenPb(dirCtx, protoImportPath, proto, g.style)
|
err = g.g.GenPb(dirCtx, protoImportPath, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenConfig(dirCtx, proto, g.style)
|
err = g.g.GenConfig(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenSvc(dirCtx, proto, g.style)
|
err = g.g.GenSvc(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenLogic(dirCtx, proto, g.style)
|
err = g.g.GenLogic(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenServer(dirCtx, proto, g.style)
|
err = g.g.GenServer(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenMain(dirCtx, proto, g.style)
|
err = g.g.GenMain(dirCtx, proto, g.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.g.GenCall(dirCtx, proto, g.style)
|
err = g.g.GenCall(dirCtx, proto, g.cfg)
|
||||||
|
|
||||||
console.NewColorConsole().MarkDone()
|
console.NewColorConsole().MarkDone()
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,14 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/tal-tech/go-zero/core/logx"
|
"github.com/tal-tech/go-zero/core/logx"
|
||||||
"github.com/tal-tech/go-zero/core/stringx"
|
"github.com/tal-tech/go-zero/core/stringx"
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var cfg = &conf.Config{
|
||||||
|
NamingFormat: "gozero",
|
||||||
|
}
|
||||||
|
|
||||||
func TestRpcGenerate(t *testing.T) {
|
func TestRpcGenerate(t *testing.T) {
|
||||||
_ = Clean()
|
_ = Clean()
|
||||||
dispatcher := NewDefaultGenerator()
|
dispatcher := NewDefaultGenerator()
|
||||||
@@ -21,7 +26,7 @@ func TestRpcGenerate(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
projectName := stringx.Rand()
|
projectName := stringx.Rand()
|
||||||
g := NewRpcGenerator(dispatcher, namingLower)
|
g := NewRpcGenerator(dispatcher, cfg)
|
||||||
|
|
||||||
// case go path
|
// case go path
|
||||||
src := filepath.Join(build.Default.GOPATH, "src")
|
src := filepath.Join(build.Default.GOPATH, "src")
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/core/collection"
|
"github.com/tal-tech/go-zero/core/collection"
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,12 +61,17 @@ func (m *default{{.serviceName}}) {{.method}}(ctx context.Context,in *{{.pbReque
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *defaultGenerator) GenCall(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetCall()
|
dir := ctx.GetCall()
|
||||||
service := proto.Service
|
service := proto.Service
|
||||||
head := util.GetHead(proto.Name)
|
head := util.GetHead(proto.Name)
|
||||||
|
|
||||||
filename := filepath.Join(dir.Filename, fmt.Sprintf("%s.go", formatFilename(service.Name, namingStyle)))
|
callFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join(dir.Filename, fmt.Sprintf("%s.go", callFilename))
|
||||||
functions, err := g.genFunction(proto.PbPackage, service)
|
functions, err := g.genFunction(proto.PbPackage, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -86,7 +93,7 @@ func (g *defaultGenerator) GenCall(ctx DirContext, proto parser.Proto, namingSty
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||||
"name": formatFilename(service.Name, namingStyle),
|
"name": callFilename,
|
||||||
"alias": strings.Join(alias.KeysStr(), util.NL),
|
"alias": strings.Join(alias.KeysStr(), util.NL),
|
||||||
"head": head,
|
"head": head,
|
||||||
"filePackage": dir.Base,
|
"filePackage": dir.Base,
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
const configTemplate = `package config
|
const configTemplate = `package config
|
||||||
@@ -18,9 +20,14 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func (g *defaultGenerator) GenConfig(ctx DirContext, _ parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetConfig()
|
dir := ctx.GetConfig()
|
||||||
fileName := filepath.Join(dir.Filename, formatFilename("config", namingStyle)+".go")
|
configFilename, err := format.FileNamingFormat(cfg.NamingFormat, "config")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := filepath.Join(dir.Filename, configFilename+".go")
|
||||||
if util.FileExists(fileName) {
|
if util.FileExists(fileName) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import "github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
import (
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
|
)
|
||||||
|
|
||||||
type Generator interface {
|
type Generator interface {
|
||||||
Prepare() error
|
Prepare() error
|
||||||
GenMain(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenCall(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenEtc(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenEtc(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenConfig(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenConfig(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenLogic(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenServer(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenSvc(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error
|
GenSvc(ctx DirContext, proto parser.Proto, cfg *conf.Config) error
|
||||||
GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, namingStyle NamingStyle) error
|
GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, cfg *conf.Config) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,10 +20,14 @@ Etcd:
|
|||||||
Key: {{.serviceName}}.rpc
|
Key: {{.serviceName}}.rpc
|
||||||
`
|
`
|
||||||
|
|
||||||
func (g *defaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetEtc()
|
dir := ctx.GetEtc()
|
||||||
serviceNameLower := formatFilename(ctx.GetMain().Base, namingStyle)
|
etcFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source())
|
||||||
fileName := filepath.Join(dir.Filename, fmt.Sprintf("%v.yaml", serviceNameLower))
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := filepath.Join(dir.Filename, fmt.Sprintf("%v.yaml", etcFilename))
|
||||||
|
|
||||||
text, err := util.LoadTemplate(category, etcTemplateFileFile, etcTemplate)
|
text, err := util.LoadTemplate(category, etcTemplateFileFile, etcTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -29,6 +35,6 @@ func (g *defaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, namingStyle Na
|
|||||||
}
|
}
|
||||||
|
|
||||||
return util.With("etc").Parse(text).SaveTo(map[string]interface{}{
|
return util.With("etc").Parse(text).SaveTo(map[string]interface{}{
|
||||||
"serviceName": strings.ToLower(stringx.From(ctx.GetMain().Base).ToCamel()),
|
"serviceName": strings.ToLower(stringx.From(ctx.GetServiceName().Source()).ToCamel()),
|
||||||
}, fileName, false)
|
}, fileName, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/core/collection"
|
"github.com/tal-tech/go-zero/core/collection"
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,10 +48,15 @@ func (l *{{.logicName}}) {{.method}} (in {{.request}}) ({{.response}}, error) {
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *defaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetLogic()
|
dir := ctx.GetLogic()
|
||||||
for _, rpc := range proto.Service.RPC {
|
for _, rpc := range proto.Service.RPC {
|
||||||
filename := filepath.Join(dir.Filename, formatFilename(rpc.Name+"_logic", namingStyle)+".go")
|
logicFilename, err := format.FileNamingFormat(cfg.NamingFormat, rpc.Name+"_logic")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join(dir.Filename, logicFilename+".go")
|
||||||
functions, err := g.genLogicFunction(proto.PbPackage, rpc)
|
functions, err := g.genLogicFunction(proto.PbPackage, rpc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,10 +47,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func (g *defaultGenerator) GenMain(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetMain()
|
mainFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source())
|
||||||
serviceNameLower := formatFilename(ctx.GetMain().Base, namingStyle)
|
if err != nil {
|
||||||
fileName := filepath.Join(dir.Filename, fmt.Sprintf("%v.go", serviceNameLower))
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := filepath.Join(ctx.GetMain().Filename, fmt.Sprintf("%v.go", mainFilename))
|
||||||
imports := make([]string, 0)
|
imports := make([]string, 0)
|
||||||
pbImport := fmt.Sprintf(`"%v"`, ctx.GetPb().Package)
|
pbImport := fmt.Sprintf(`"%v"`, ctx.GetPb().Package)
|
||||||
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
|
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
|
||||||
@@ -63,7 +68,7 @@ func (g *defaultGenerator) GenMain(ctx DirContext, proto parser.Proto, namingSty
|
|||||||
|
|
||||||
return util.With("main").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
return util.With("main").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
|
||||||
"head": head,
|
"head": head,
|
||||||
"serviceName": strings.ToLower(stringx.From(ctx.GetMain().Base).ToCamel()),
|
"serviceName": strings.ToLower(ctx.GetServiceName().ToCamel()),
|
||||||
"imports": strings.Join(imports, util.NL),
|
"imports": strings.Join(imports, util.NL),
|
||||||
"pkg": proto.PbPackage,
|
"pkg": proto.PbPackage,
|
||||||
"serviceNew": stringx.From(proto.Service.Name).ToCamel(),
|
"serviceNew": stringx.From(proto.Service.Name).ToCamel(),
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *defaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, _ *conf.Config) error {
|
||||||
dir := ctx.GetPb()
|
dir := ctx.GetPb()
|
||||||
cw := new(bytes.Buffer)
|
cw := new(bytes.Buffer)
|
||||||
base := filepath.Dir(proto.Src)
|
base := filepath.Dir(proto.Src)
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/core/collection"
|
"github.com/tal-tech/go-zero/core/collection"
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ func (s *{{.server}}Server) {{.method}} (ctx context.Context, in {{.request}}) (
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *defaultGenerator) GenServer(ctx DirContext, proto parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetServer()
|
dir := ctx.GetServer()
|
||||||
logicImport := fmt.Sprintf(`"%v"`, ctx.GetLogic().Package)
|
logicImport := fmt.Sprintf(`"%v"`, ctx.GetLogic().Package)
|
||||||
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
|
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
|
||||||
@@ -54,7 +56,12 @@ func (g *defaultGenerator) GenServer(ctx DirContext, proto parser.Proto, namingS
|
|||||||
|
|
||||||
head := util.GetHead(proto.Name)
|
head := util.GetHead(proto.Name)
|
||||||
service := proto.Service
|
service := proto.Service
|
||||||
serverFile := filepath.Join(dir.Filename, formatFilename(service.Name+"_server", namingStyle)+".go")
|
serverFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name+"_server")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
serverFile := filepath.Join(dir.Filename, serverFilename+".go")
|
||||||
funcList, err := g.genFunctions(proto.PbPackage, service)
|
funcList, err := g.genFunctions(proto.PbPackage, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
conf "github.com/tal-tech/go-zero/tools/goctl/config"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
const svcTemplate = `package svc
|
const svcTemplate = `package svc
|
||||||
@@ -23,9 +25,14 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
func (g *defaultGenerator) GenSvc(ctx DirContext, _ parser.Proto, namingStyle NamingStyle) error {
|
func (g *defaultGenerator) GenSvc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
|
||||||
dir := ctx.GetSvc()
|
dir := ctx.GetSvc()
|
||||||
fileName := filepath.Join(dir.Filename, formatFilename("service_context", namingStyle)+".go")
|
svcFilename, err := format.FileNamingFormat(cfg.NamingFormat, "service_context")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := filepath.Join(dir.Filename, svcFilename+".go")
|
||||||
text, err := util.LoadTemplate(category, svcTemplateFile, svcTemplate)
|
text, err := util.LoadTemplate(category, svcTemplateFile, svcTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type (
|
|||||||
GetSvc() Dir
|
GetSvc() Dir
|
||||||
GetPb() Dir
|
GetPb() Dir
|
||||||
GetMain() Dir
|
GetMain() Dir
|
||||||
|
GetServiceName() stringx.String
|
||||||
}
|
}
|
||||||
|
|
||||||
Dir struct {
|
Dir struct {
|
||||||
@@ -41,7 +42,8 @@ type (
|
|||||||
Package string
|
Package string
|
||||||
}
|
}
|
||||||
defaultDirContext struct {
|
defaultDirContext struct {
|
||||||
inner map[string]Dir
|
inner map[string]Dir
|
||||||
|
serviceName stringx.String
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,8 +112,10 @@ func mkdir(ctx *ctx.ProjectContext, proto parser.Proto) (DirContext, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
serviceName := strings.TrimSuffix(proto.Name, filepath.Ext(proto.Name))
|
||||||
return &defaultDirContext{
|
return &defaultDirContext{
|
||||||
inner: inner,
|
inner: inner,
|
||||||
|
serviceName: stringx.From(strings.ReplaceAll(serviceName, "-", "")),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +155,10 @@ func (d *defaultDirContext) GetMain() Dir {
|
|||||||
return d.inner[wd]
|
return d.inner[wd]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *defaultDirContext) GetServiceName() stringx.String {
|
||||||
|
return d.serviceName
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Dir) Valid() bool {
|
func (d *Dir) Valid() bool {
|
||||||
return len(d.Filename) > 0 && len(d.Package) > 0
|
return len(d.Filename) > 0 && len(d.Package) > 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
type NamingStyle = string
|
|
||||||
|
|
||||||
const (
|
|
||||||
namingLower NamingStyle = "lower"
|
|
||||||
namingCamel NamingStyle = "camel"
|
|
||||||
namingSnake NamingStyle = "snake"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsNamingValid validates whether the namingStyle is valid or not,return
|
|
||||||
// namingStyle and true if it is valid, or else return empty string
|
|
||||||
// and false, and it is a valid value even namingStyle is empty string
|
|
||||||
func IsNamingValid(namingStyle string) (NamingStyle, bool) {
|
|
||||||
if len(namingStyle) == 0 {
|
|
||||||
namingStyle = namingLower
|
|
||||||
}
|
|
||||||
switch namingStyle {
|
|
||||||
case namingLower, namingCamel, namingSnake:
|
|
||||||
return namingStyle, true
|
|
||||||
default:
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package generator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIsNamingValid(t *testing.T) {
|
|
||||||
style, valid := IsNamingValid("")
|
|
||||||
assert.True(t, valid)
|
|
||||||
assert.Equal(t, namingLower, style)
|
|
||||||
|
|
||||||
_, valid = IsNamingValid("lower1")
|
|
||||||
assert.False(t, valid)
|
|
||||||
|
|
||||||
_, valid = IsNamingValid("lower")
|
|
||||||
assert.True(t, valid)
|
|
||||||
|
|
||||||
_, valid = IsNamingValid("snake")
|
|
||||||
assert.True(t, valid)
|
|
||||||
|
|
||||||
_, valid = IsNamingValid("camel")
|
|
||||||
assert.True(t, valid)
|
|
||||||
}
|
|
||||||
@@ -8,13 +8,21 @@ import (
|
|||||||
|
|
||||||
const goctlDir = ".goctl"
|
const goctlDir = ".goctl"
|
||||||
|
|
||||||
func GetTemplateDir(category string) (string, error) {
|
func GetGoctlHome() (string, error) {
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
return filepath.Join(home, goctlDir), nil
|
||||||
|
}
|
||||||
|
|
||||||
return filepath.Join(home, goctlDir, category), nil
|
func GetTemplateDir(category string) (string, error) {
|
||||||
|
goctlHome, err := GetGoctlHome()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(goctlHome, category), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitTemplates(category string, templates map[string]string) error {
|
func InitTemplates(category string, templates map[string]string) error {
|
||||||
|
|||||||
155
tools/goctl/util/format/format.go
Normal file
155
tools/goctl/util/format/format.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package format
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagGo = "GO"
|
||||||
|
flagZero = "ZERO"
|
||||||
|
|
||||||
|
unknown style = iota
|
||||||
|
title
|
||||||
|
lower
|
||||||
|
upper
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrNamingFormat = errors.New("unsupported format")
|
||||||
|
|
||||||
|
type (
|
||||||
|
styleFormat struct {
|
||||||
|
before string
|
||||||
|
through string
|
||||||
|
after string
|
||||||
|
goStyle style
|
||||||
|
zeroStyle style
|
||||||
|
}
|
||||||
|
|
||||||
|
style int
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileNamingFormat is used to format the file name. You can define the format style
|
||||||
|
// through the go and zero formatting characters. For example, you can define the snake
|
||||||
|
// format as go_zero, and the camel case format as goZero. You can even specify the split
|
||||||
|
// character, such as go#Zero, theoretically any combination can be used, but the prerequisite
|
||||||
|
// must meet the naming conventions of each operating system file name.
|
||||||
|
// Note: Formatting is based on snake or camel string
|
||||||
|
func FileNamingFormat(format, content string) (string, error) {
|
||||||
|
upperFormat := strings.ToUpper(format)
|
||||||
|
indexGo := strings.Index(upperFormat, flagGo)
|
||||||
|
indexZero := strings.Index(upperFormat, flagZero)
|
||||||
|
if indexGo < 0 || indexZero < 0 || indexGo > indexZero {
|
||||||
|
return "", ErrNamingFormat
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
before, through, after string
|
||||||
|
flagGo, flagZero string
|
||||||
|
goStyle, zeroStyle style
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
before = format[:indexGo]
|
||||||
|
flagGo = format[indexGo : indexGo+2]
|
||||||
|
through = format[indexGo+2 : indexZero]
|
||||||
|
flagZero = format[indexZero : indexZero+4]
|
||||||
|
after = format[indexZero+4:]
|
||||||
|
|
||||||
|
goStyle, err = getStyle(flagGo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
zeroStyle, err = getStyle(flagZero)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var formatStyle styleFormat
|
||||||
|
formatStyle.goStyle = goStyle
|
||||||
|
formatStyle.zeroStyle = zeroStyle
|
||||||
|
formatStyle.before = before
|
||||||
|
formatStyle.through = through
|
||||||
|
formatStyle.after = after
|
||||||
|
return doFormat(formatStyle, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doFormat(f styleFormat, content string) (string, error) {
|
||||||
|
splits, err := split(content)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var join []string
|
||||||
|
for index, split := range splits {
|
||||||
|
if index == 0 {
|
||||||
|
join = append(join, transferTo(split, f.goStyle))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
join = append(join, transferTo(split, f.zeroStyle))
|
||||||
|
}
|
||||||
|
joined := strings.Join(join, f.through)
|
||||||
|
return f.before + joined + f.after, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func transferTo(in string, style style) string {
|
||||||
|
switch style {
|
||||||
|
case upper:
|
||||||
|
return strings.ToUpper(in)
|
||||||
|
case lower:
|
||||||
|
return strings.ToLower(in)
|
||||||
|
case title:
|
||||||
|
return strings.Title(in)
|
||||||
|
default:
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func split(content string) ([]string, error) {
|
||||||
|
var (
|
||||||
|
list []string
|
||||||
|
reader = strings.NewReader(content)
|
||||||
|
buffer = bytes.NewBuffer(nil)
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
r, _, err := reader.ReadRune()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
list = append(list, buffer.String())
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if r == '_' {
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
list = append(list, buffer.String())
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if r >= 'A' && r <= 'Z' {
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
list = append(list, buffer.String())
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
|
}
|
||||||
|
buffer.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStyle(flag string) (style, error) {
|
||||||
|
compare := strings.ToLower(flag)
|
||||||
|
switch flag {
|
||||||
|
case strings.ToLower(compare):
|
||||||
|
return lower, nil
|
||||||
|
case strings.ToUpper(compare):
|
||||||
|
return upper, nil
|
||||||
|
case strings.Title(compare):
|
||||||
|
return title, nil
|
||||||
|
default:
|
||||||
|
return unknown, fmt.Errorf("unexpected format: %s", flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
112
tools/goctl/util/format/format_test.go
Normal file
112
tools/goctl/util/format/format_test.go
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
package format
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSplit(t *testing.T) {
|
||||||
|
list, err := split("A")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"A"}, list)
|
||||||
|
|
||||||
|
list, err = split("goZero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"go", "Zero"}, list)
|
||||||
|
|
||||||
|
list, err = split("Gozero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"Gozero"}, list)
|
||||||
|
|
||||||
|
list, err = split("go_zero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"go", "zero"}, list)
|
||||||
|
|
||||||
|
list, err = split("talGo_zero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"tal", "Go", "zero"}, list)
|
||||||
|
|
||||||
|
list, err = split("GOZERO")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"G", "O", "Z", "E", "R", "O"}, list)
|
||||||
|
|
||||||
|
list, err = split("gozero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"gozero"}, list)
|
||||||
|
|
||||||
|
list, err = split("")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 0, len(list))
|
||||||
|
|
||||||
|
list, err = split("a_b_CD_EF")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"a", "b", "C", "D", "E", "F"}, list)
|
||||||
|
|
||||||
|
list, err = split("_")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 0, len(list))
|
||||||
|
|
||||||
|
list, err = split("__")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 0, len(list))
|
||||||
|
|
||||||
|
list, err = split("_A")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"A"}, list)
|
||||||
|
|
||||||
|
list, err = split("_A_")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"A"}, list)
|
||||||
|
|
||||||
|
list, err = split("A_")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"A"}, list)
|
||||||
|
|
||||||
|
list, err = split("welcome_to_go_zero")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, []string{"welcome", "to", "go", "zero"}, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileNamingFormat(t *testing.T) {
|
||||||
|
testFileNamingFormat(t, "gozero", "welcome_to_go_zero", "welcometogozero")
|
||||||
|
testFileNamingFormat(t, "_go#zero_", "welcome_to_go_zero", "_welcome#to#go#zero_")
|
||||||
|
testFileNamingFormat(t, "Go#zero", "welcome_to_go_zero", "Welcome#to#go#zero")
|
||||||
|
testFileNamingFormat(t, "Go#Zero", "welcome_to_go_zero", "Welcome#To#Go#Zero")
|
||||||
|
testFileNamingFormat(t, "Go_Zero", "welcome_to_go_zero", "Welcome_To_Go_Zero")
|
||||||
|
testFileNamingFormat(t, "go_Zero", "welcome_to_go_zero", "welcome_To_Go_Zero")
|
||||||
|
testFileNamingFormat(t, "goZero", "welcome_to_go_zero", "welcomeToGoZero")
|
||||||
|
testFileNamingFormat(t, "GoZero", "welcome_to_go_zero", "WelcomeToGoZero")
|
||||||
|
testFileNamingFormat(t, "GOZero", "welcome_to_go_zero", "WELCOMEToGoZero")
|
||||||
|
testFileNamingFormat(t, "GoZERO", "welcome_to_go_zero", "WelcomeTOGOZERO")
|
||||||
|
testFileNamingFormat(t, "GOZERO", "welcome_to_go_zero", "WELCOMETOGOZERO")
|
||||||
|
testFileNamingFormat(t, "GO*ZERO", "welcome_to_go_zero", "WELCOME*TO*GO*ZERO")
|
||||||
|
testFileNamingFormat(t, "[GO#ZERO]", "welcome_to_go_zero", "[WELCOME#TO#GO#ZERO]")
|
||||||
|
testFileNamingFormat(t, "{go###zero}", "welcome_to_go_zero", "{welcome###to###go###zero}")
|
||||||
|
testFileNamingFormat(t, "{go###zerogo_zero}", "welcome_to_go_zero", "{welcome###to###go###zerogo_zero}")
|
||||||
|
testFileNamingFormat(t, "GogoZerozero", "welcome_to_go_zero", "WelcomegoTogoGogoZerozero")
|
||||||
|
testFileNamingFormat(t, "前缀GoZero后缀", "welcome_to_go_zero", "前缀WelcomeToGoZero后缀")
|
||||||
|
testFileNamingFormat(t, "GoZero", "welcometogozero", "Welcometogozero")
|
||||||
|
testFileNamingFormat(t, "GoZero", "WelcomeToGoZero", "WelcomeToGoZero")
|
||||||
|
testFileNamingFormat(t, "gozero", "WelcomeToGoZero", "welcometogozero")
|
||||||
|
testFileNamingFormat(t, "go_zero", "WelcomeToGoZero", "welcome_to_go_zero")
|
||||||
|
testFileNamingFormat(t, "Go_Zero", "WelcomeToGoZero", "Welcome_To_Go_Zero")
|
||||||
|
testFileNamingFormat(t, "Go_Zero", "", "")
|
||||||
|
testFileNamingFormatErr(t, "go", "")
|
||||||
|
testFileNamingFormatErr(t, "gOZero", "")
|
||||||
|
testFileNamingFormatErr(t, "zero", "")
|
||||||
|
testFileNamingFormatErr(t, "goZEro", "welcome_to_go_zero")
|
||||||
|
testFileNamingFormatErr(t, "goZERo", "welcome_to_go_zero")
|
||||||
|
testFileNamingFormatErr(t, "zerogo", "welcome_to_go_zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFileNamingFormat(t *testing.T, format, in, expected string) {
|
||||||
|
format, err := FileNamingFormat(format, in)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, expected, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFileNamingFormatErr(t *testing.T, format, in string) {
|
||||||
|
_, err := FileNamingFormat(format, in)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
41
tools/goctl/util/name/naming.go
Normal file
41
tools/goctl/util/name/naming.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package name
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NamingStyle = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
NamingLower NamingStyle = "lower"
|
||||||
|
NamingCamel NamingStyle = "camel"
|
||||||
|
NamingSnake NamingStyle = "snake"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsNamingValid validates whether the namingStyle is valid or not,return
|
||||||
|
// namingStyle and true if it is valid, or else return empty string
|
||||||
|
// and false, and it is a valid value even namingStyle is empty string
|
||||||
|
func IsNamingValid(namingStyle string) (NamingStyle, bool) {
|
||||||
|
if len(namingStyle) == 0 {
|
||||||
|
namingStyle = NamingLower
|
||||||
|
}
|
||||||
|
switch namingStyle {
|
||||||
|
case NamingLower, NamingCamel, NamingSnake:
|
||||||
|
return namingStyle, true
|
||||||
|
default:
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatFilename(filename string, style NamingStyle) string {
|
||||||
|
switch style {
|
||||||
|
case NamingCamel:
|
||||||
|
return stringx.From(filename).ToCamel()
|
||||||
|
case NamingSnake:
|
||||||
|
return stringx.From(filename).ToSnake()
|
||||||
|
default:
|
||||||
|
return strings.ToLower(stringx.From(filename).ToCamel())
|
||||||
|
}
|
||||||
|
}
|
||||||
35
tools/goctl/util/name/naming_test.go
Normal file
35
tools/goctl/util/name/naming_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package name
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsNamingValid(t *testing.T) {
|
||||||
|
style, valid := IsNamingValid("")
|
||||||
|
assert.True(t, valid)
|
||||||
|
assert.Equal(t, NamingLower, style)
|
||||||
|
|
||||||
|
_, valid = IsNamingValid("lower1")
|
||||||
|
assert.False(t, valid)
|
||||||
|
|
||||||
|
_, valid = IsNamingValid("lower")
|
||||||
|
assert.True(t, valid)
|
||||||
|
|
||||||
|
_, valid = IsNamingValid("snake")
|
||||||
|
assert.True(t, valid)
|
||||||
|
|
||||||
|
_, valid = IsNamingValid("camel")
|
||||||
|
assert.True(t, valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFormatFilename(t *testing.T) {
|
||||||
|
assert.Equal(t, "abc", FormatFilename("a_b_c", NamingLower))
|
||||||
|
assert.Equal(t, "ABC", FormatFilename("a_b_c", NamingCamel))
|
||||||
|
assert.Equal(t, "a_b_c", FormatFilename("a_b_c", NamingSnake))
|
||||||
|
assert.Equal(t, "a", FormatFilename("a", NamingSnake))
|
||||||
|
assert.Equal(t, "A", FormatFilename("a", NamingCamel))
|
||||||
|
// no flag to convert to snake
|
||||||
|
assert.Equal(t, "abc", FormatFilename("abc", NamingSnake))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user