refine goctl rpc generator

master
kevin 4 years ago
parent db16115037
commit 72132ce399

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 140 KiB

@ -102,7 +102,7 @@
* 测试API Gateway服务 * 测试API Gateway服务
```shell ```shell
curl -i "http://localhost:8888/shorten?url=a" curl -i "http://localhost:8888/shorten?url=http://www.xiaoheiban.cn"
``` ```
返回如下: 返回如下:
@ -116,6 +116,8 @@
{"shortUrl":""} {"shortUrl":""}
``` ```
可以看到我们API Gateway其实啥也没干就返回了个空值接下来我们会在rpc服务里实现业务逻辑
* 可以修改`internal/svc/servicecontext.go`来传递服务依赖(如果需要) * 可以修改`internal/svc/servicecontext.go`来传递服务依赖(如果需要)
* 实现逻辑可以修改`internal/logic`下的对应文件 * 实现逻辑可以修改`internal/logic`下的对应文件
@ -125,11 +127,65 @@
## 4. 编写shorten rpc服务未完 ## 4. 编写shorten rpc服务未完
* 编写`shorten.proto`文件 * 编写`shorten.proto`文件
可以通过命令生成proto文件模板
```shell
goctl rpc template -o shorten.proto
```
修改后文件内容如下:
```protobuf
syntax = "proto3";
package shorten;
message shortenReq {
string url = 1;
}
message shortenResp {
string key = 1;
}
service shortener {
rpc shorten(shortenReq) returns(shortenResp);
}
```
* 用`goctl`生成rpc代码 * 用`goctl`生成rpc代码
## 5. 编写expand rpc服务未完 ## 5. 编写expand rpc服务未完
* 编写`expand.proto`文件 * 编写`expand.proto`文件
可以通过命令生成proto文件模板
```shell
goctl rpc template -o expand.proto
```
修改后文件内容如下:
```protobuf
syntax = "proto3";
package expand;
message expandReq {
string key = 1;
}
message expandResp {
string url = 1;
}
service expander {
rpc expand(expandReq) returns(expandResp);
}
```
* 用`goctl`生成rpc代码 * 用`goctl`生成rpc代码
## 6. 修改API Gateway代码调用shorten/expand rpc服务未完 ## 6. 修改API Gateway代码调用shorten/expand rpc服务未完
@ -150,6 +206,16 @@
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
``` ```
* 创建DB和table
```sql
create database gozero;
```
```sql
source shorturl.sql;
```
* 在`rpc/model`目录下执行如下命令生成CRUD+cache代码`-c`表示使用`redis cache` * 在`rpc/model`目录下执行如下命令生成CRUD+cache代码`-c`表示使用`redis cache`
```shell ```shell
@ -198,3 +264,9 @@
## 10. Benchmark未完 ## 10. Benchmark未完
## 11. 总结(未完) ## 11. 总结(未完)
可以看到go-zero不只是一个框架更是一个建立在框架+工具基础上的,简化和规范了整个微服务构建的技术体系。
我们一直强调**工具大于约定和文档**。
另外,我们在保持简单的同时也尽可能把微服务治理的复杂度封装到了框架内部,极大的降低了开发人员的心智负担,使得业务开发得以快速推进。

@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/urfave/cli"
"github.com/tal-tech/go-zero/core/logx" "github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/api/apigen" "github.com/tal-tech/go-zero/tools/goctl/api/apigen"
"github.com/tal-tech/go-zero/tools/goctl/api/dartgen" "github.com/tal-tech/go-zero/tools/goctl/api/dartgen"
@ -21,6 +19,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/feature" "github.com/tal-tech/go-zero/tools/goctl/feature"
model "github.com/tal-tech/go-zero/tools/goctl/model/sql/command" model "github.com/tal-tech/go-zero/tools/goctl/model/sql/command"
rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/command" rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/command"
"github.com/urfave/cli"
) )
var ( var (
@ -196,7 +195,7 @@ var (
Subcommands: []cli.Command{ Subcommands: []cli.Command{
{ {
Name: "template", Name: "template",
Usage: `generate proto template"`, Usage: `generate proto template`,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "out, o", Name: "out, o",
@ -211,7 +210,7 @@ var (
}, },
{ {
Name: "proto", Name: "proto",
Usage: `generate rpc from proto"`, Usage: `generate rpc from proto`,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "src, s", Name: "src, s",
@ -227,7 +226,7 @@ var (
}, },
cli.StringFlag{ cli.StringFlag{
Name: "shared", Name: "shared",
Usage: `the dir of the shared file,default path is "${pwd}/shared. [option]"`, Usage: `the dir of the shared file,default path is "${pwd}/shared. [option]`,
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "idea", Name: "idea",

@ -17,7 +17,7 @@ $ goctl rpc template -o=user.proto
```golang ```golang
syntax = "proto3"; syntax = "proto3";
package remoteuser; package remote;
message Request { message Request {
// 用户名 // 用户名
@ -33,7 +33,7 @@ message Response {
string gender = 2; string gender = 2;
} }
service User{ service User {
// 登录 // 登录
rpc Login(Request)returns(Response); rpc Login(Request)returns(Response);
} }
@ -146,7 +146,7 @@ OPTIONS:
* proto不支持外部依赖包引入message不支持inline * proto不支持外部依赖包引入message不支持inline
* 目前main文件、shared文件、handler文件会被强制覆盖而和开发人员手动需要编写的则不会覆盖生成这一类在代码头部均有 * 目前main文件、shared文件、handler文件会被强制覆盖而和开发人员手动需要编写的则不会覆盖生成这一类在代码头部均有
```shell script ```shell script
// Code generated by goctl. DO NOT EDIT. // Code generated by goctl. DO NOT EDIT!
// Source: xxx.proto // Source: xxx.proto
``` ```
的标识,请注意不要将也写业务性代码写在里面。 的标识,请注意不要将也写业务性代码写在里面。

@ -4,7 +4,7 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/tal-tech/go-zero/tools/goctl/rpc/ctx" "github.com/tal-tech/go-zero/tools/goctl/rpc/ctx"
"github.com/tal-tech/go-zero/tools/goctl/rpc/goen" "github.com/tal-tech/go-zero/tools/goctl/rpc/gen"
) )
func Rpc(c *cli.Context) error { func Rpc(c *cli.Context) error {

@ -16,9 +16,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/console" "github.com/tal-tech/go-zero/tools/goctl/util/console"
) )
var ( var errProtobufNotFound = errors.New("github.com/golang/protobuf is not found,please ensure you has already [go get github.com/golang/protobuf]")
errProtobufNotFound = errors.New("github.com/golang/protobuf is not found,please ensure you has already [go get github.com/golang/protobuf]")
)
const ( const (
constGo = "go" constGo = "go"
@ -51,7 +49,7 @@ type (
) )
func prepare(log console.Console) (*Project, error) { func prepare(log console.Console) (*Project, error) {
log.Info("check go env ...") log.Info("checking go env...")
_, err := exec.LookPath(constGo) _, err := exec.LookPath(constGo)
if err != nil { if err != nil {
return nil, err return nil, err
@ -109,11 +107,6 @@ func prepare(log console.Console) (*Project, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
protobufModule, err = matchProtoBuf(data)
if err != nil {
return nil, err
}
} else { } else {
if goModCache == "" { if goModCache == "" {
goModCache = src goModCache = src
@ -180,21 +173,6 @@ func prepare(log console.Console) (*Project, error) {
}, nil }, nil
} }
// github.com/golang/protobuf@{version}
func matchProtoBuf(data []byte) (string, error) {
text := string(data)
re := regexp.MustCompile(`(?m)(github.com/golang/protobuf)\s+(v[0-9.]+)`)
matches := re.FindAllStringSubmatch(text, -1)
if len(matches) == 0 {
return "", errProtobufNotFound
}
groups := matches[0]
if len(groups) < 3 {
return "", errProtobufNotFound
}
return fmt.Sprintf("%s@%s", groups[1], groups[2]), nil
}
func matchModule(data []byte) (string, error) { func matchModule(data []byte) (string, error) {
text := string(data) text := string(data)
re := regexp.MustCompile(`(?m)^\s*module\s+[a-z0-9/\-.]+$`) re := regexp.MustCompile(`(?m)^\s*module\s+[a-z0-9/\-.]+$`)
@ -204,5 +182,6 @@ func matchModule(data []byte) (string, error) {
index := strings.Index(target, "module") index := strings.Index(target, "module")
return strings.TrimSpace(target[index+6:]), nil return strings.TrimSpace(target[index+6:]), nil
} }
return "", nil return "", nil
} }

@ -34,7 +34,7 @@ func NewDefaultRpcGenerator(ctx *ctx.RpcContext) *defaultRpcGenerator {
} }
func (g *defaultRpcGenerator) Generate() (err error) { func (g *defaultRpcGenerator) Generate() (err error) {
g.Ctx.Info("code generating...") g.Ctx.Info("generating code...")
defer func() { defer func() {
if err == nil { if err == nil {
g.Ctx.Success("Done.") g.Ctx.Success("Done.")

@ -8,15 +8,13 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var configTemplate = `package config const configTemplate = `package config
import "github.com/tal-tech/go-zero/rpcx" import "github.com/tal-tech/go-zero/rpcx"
type ( type Config struct {
Config struct {
rpcx.RpcServerConf rpcx.RpcServerConf
} }
)
` `
func (g *defaultRpcGenerator) genConfig() error { func (g *defaultRpcGenerator) genConfig() error {

@ -0,0 +1,30 @@
package gogen
import (
"fmt"
"path/filepath"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
const etcTemplate = `Name: {{.serviceName}}.rpc
Log:
Mode: console
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- 127.0.0.1:6379
Key: {{.serviceName}}.rpc
`
func (g *defaultRpcGenerator) genEtc() error {
etdDir := g.dirM[dirEtc]
fileName := filepath.Join(etdDir, fmt.Sprintf("%v.yaml", g.Ctx.ServiceName.Lower()))
if util.FileExists(fileName) {
return nil
}
return util.With("etc").Parse(etcTemplate).SaveTo(map[string]interface{}{
"serviceName": g.Ctx.ServiceName.Lower(),
}, fileName, false)
}

@ -8,18 +8,14 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var ( const (
remoteTemplate = `{{.head}} remoteTemplate = `{{.head}}
package handler package handler
import ( import {{.imports}}
{{.imports}}
)
type ( type {{.types}}
{{.types}}
)
{{.newFuncs}} {{.newFuncs}}
` `
@ -33,9 +29,11 @@ import (
{{.imports}} {{.imports}}
) )
type {{.server}}Server struct{}
{{if .hasComment}}{{.comment}}{{end}} {{if .hasComment}}{{.comment}}{{end}}
func (s *{{.server}}Server) {{.method}} (ctx context.Context, in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) { func (s *{{.server}}Server) {{.method}} (ctx context.Context, in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) {
l:=logic.New{{.logicName}}(ctx,s.svcCtx) l := logic.New{{.logicName}}(ctx,s.svcCtx)
return l.{{.method}}(in) return l.{{.method}}(in)
} }
` `

@ -10,29 +10,26 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var ( const (
logicTemplate = `package logic logicTemplate = `package logic
import ( import (
"context" "context"
{{.imports}} {{.imports}}
"github.com/tal-tech/go-zero/core/logx" "github.com/tal-tech/go-zero/core/logx"
) )
type ( type {{.logicName}} struct {
{{.logicName}} struct {
ctx context.Context ctx context.Context
logx.Logger logx.Logger
// todo: add your logic here and delete this line }
}
)
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} { func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
return &{{.logicName}}{ return &{{.logicName}}{
ctx: ctx, ctx: ctx,
Logger: logx.WithContext(ctx), Logger: logx.WithContext(ctx),
// todo: add your logic here and delete this line
} }
} }
{{.functions}} {{.functions}}
@ -40,6 +37,7 @@ func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logic
logicFunctionTemplate = `{{if .hasComment}}{{.comment}}{{end}} logicFunctionTemplate = `{{if .hasComment}}{{.comment}}{{end}}
func (l *{{.logicName}}) {{.method}} (in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) { func (l *{{.logicName}}) {{.method}} (in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) {
var resp {{.package}}.{{.response}} var resp {{.package}}.{{.response}}
// todo: add your logic here and delete this line // todo: add your logic here and delete this line
return &resp,nil return &resp,nil

@ -9,7 +9,7 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var mainTemplate = `{{.head}} const mainTemplate = `{{.head}}
package main package main
@ -18,15 +18,14 @@ import (
"fmt" "fmt"
"log" "log"
"google.golang.org/grpc" {{.imports}}
"github.com/tal-tech/go-zero/core/conf" "github.com/tal-tech/go-zero/core/conf"
"github.com/tal-tech/go-zero/rpcx" "github.com/tal-tech/go-zero/rpcx"
"google.golang.org/grpc"
{{.imports}}
) )
var configFile = flag.String("f", "etc/{{.serviceName}}.json", "the config file") var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
func main() { func main() {
flag.Parse() flag.Parse()
@ -42,10 +41,10 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
s.Start() s.Start()
} }
` `
func (g *defaultRpcGenerator) genMain() error { func (g *defaultRpcGenerator) genMain() error {

@ -8,7 +8,6 @@ import (
"strings" "strings"
"github.com/dsymonds/gotoc/parser" "github.com/dsymonds/gotoc/parser"
"github.com/tal-tech/go-zero/core/lang" "github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx" "github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
astParser "github.com/tal-tech/go-zero/tools/goctl/rpc/parser" astParser "github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
@ -80,6 +79,9 @@ protoc -I=%s --go_out=plugins=grpc:%s %s`, filepath.Join(g.Ctx.GoPath, "bin"), s
return err return err
} }
if len(stdout) > 0 {
g.Ctx.Info(stdout) g.Ctx.Info(stdout)
}
return nil return nil
} }

@ -12,10 +12,10 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var ( const (
sharedTemplateText = `{{.head}} sharedTemplateText = `{{.head}}
//go:generate mockgen -destination ./mock{{.name}}model.go -package {{.filePackage}} -source $GOFILE //go:generate mockgen -destination ./{{.name}}model_mock.go -package {{.filePackage}} -source $GOFILE
package {{.filePackage}} package {{.filePackage}}
@ -23,6 +23,7 @@ import (
"context" "context"
{{.package}} {{.package}}
"github.com/tal-tech/go-zero/core/jsonx" "github.com/tal-tech/go-zero/core/jsonx"
"github.com/tal-tech/go-zero/rpcx" "github.com/tal-tech/go-zero/rpcx"
) )
@ -31,13 +32,13 @@ type (
{{.serviceName}}Model interface { {{.serviceName}}Model interface {
{{.interface}} {{.interface}}
} }
default{{.serviceName}}Model struct { default{{.serviceName}}Model struct {
cli rpcx.Client cli rpcx.Client
} }
) )
func New{{.serviceName}}Model(cli rpcx.Client) {{.serviceName}}Model {
func NewDefault{{.serviceName}}Model(cli rpcx.Client) {{.serviceName}}Model {
return &default{{.serviceName}}Model{ return &default{{.serviceName}}Model{
cli: cli, cli: cli,
} }
@ -49,51 +50,52 @@ func NewDefault{{.serviceName}}Model(cli rpcx.Client) {{.serviceName}}Model {
package {{.filePackage}} package {{.filePackage}}
import ( import "errors"
"errors"
)
var ( var errJsonConvert = errors.New("json convert error")
errJsonConvert = errors.New("json convert error")
)
{{.types}} {{.types}}
` `
sharedInterfaceFunctionTemplate = `{{if .hasComment}}{{.comment}} sharedInterfaceFunctionTemplate = `{{if .hasComment}}{{.comment}}
{{end}}{{.method}}(ctx context.Context,in *{{.pbRequest}}) {{if .hasResponse}}(*{{.pbResponse}},{{end}} error{{if .hasResponse}}){{end}}` {{end}}{{.method}}(ctx context.Context,in *{{.pbRequest}}) {{if .hasResponse}}(*{{.pbResponse}},{{end}} error{{if .hasResponse}}){{end}}`
sharedFunctionTemplate = ` sharedFunctionTemplate = `
{{if .hasComment}}{{.comment}}{{end}} {{if .hasComment}}{{.comment}}{{end}}
func (m *default{{.rpcServiceName}}Model) {{.method}}(ctx context.Context,in *{{.pbRequest}}) {{if .hasResponse}}(*{{.pbResponse}},{{end}} error{{if .hasResponse}}){{end}} { func (m *default{{.rpcServiceName}}Model) {{.method}}(ctx context.Context,in *{{.pbRequest}}) {{if .hasResponse}}(*{{.pbResponse}},{{end}} error{{if .hasResponse}}){{end}} {
conn:= m.cli.Conn() client := {{.package}}.New{{.rpcServiceName}}Client(m.cli.Conn())
client := {{.package}}.New{{.rpcServiceName}}Client(conn)
var request {{.package}}.{{.pbRequest}} var request {{.package}}.{{.pbRequest}}
bts, err := jsonx.Marshal(in) bts, err := jsonx.Marshal(in)
if err != nil { if err != nil {
return {{if .hasResponse}}nil,{{end}}errJsonConvert return {{if .hasResponse}}nil, {{end}}errJsonConvert
} }
err = jsonx.Unmarshal(bts, &request) err = jsonx.Unmarshal(bts, &request)
if err != nil { if err != nil {
return {{if .hasResponse}}nil,{{end}}errJsonConvert return {{if .hasResponse}}nil, {{end}}errJsonConvert
} }
{{if .hasResponse}}resp,err:={{else}}_,err={{end}}client.{{.method}}(ctx, &request)
{{if .hasResponse}}if err!=nil{ {{if .hasResponse}}resp, err := {{else}}_, err = {{end}}client.{{.method}}(ctx, &request)
return nil,err {{if .hasResponse}}if err != nil{
return nil, err
} }
var ret {{.pbResponse}} var ret {{.pbResponse}}
bts,err=jsonx.Marshal(resp) bts, err = jsonx.Marshal(resp)
if err!=nil{ if err != nil{
return nil,errJsonConvert return nil, errJsonConvert
} }
err=jsonx.Unmarshal(bts,&ret)
if err!=nil{ err = jsonx.Unmarshal(bts, &ret)
return nil,errJsonConvert if err != nil{
return nil, errJsonConvert
} }
return &ret, nil{{else}}if err!=nil {
return &ret, nil{{else}}if err != nil {
return err return err
} }
return nil{{end}} return nil{{end}}
}` }
`
) )
func (g *defaultRpcGenerator) genShared() error { func (g *defaultRpcGenerator) genShared() error {
@ -127,7 +129,7 @@ func (g *defaultRpcGenerator) genShared() error {
if err != nil { if err != nil {
return err return err
} }
mockFile := filepath.Join(g.Ctx.SharedDir, fmt.Sprintf("mock%smodel.go", service.Name.Lower())) mockFile := filepath.Join(g.Ctx.SharedDir, fmt.Sprintf("%smodel_mock.go", service.Name.Lower()))
os.Remove(mockFile) os.Remove(mockFile)
err = util.With("shared").GoFmt(true).Parse(sharedTemplateText).SaveTo(map[string]interface{}{ err = util.With("shared").GoFmt(true).Parse(sharedTemplateText).SaveTo(map[string]interface{}{
"name": service.Name.Lower(), "name": service.Name.Lower(),

@ -7,16 +7,13 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util"
) )
var svcTemplate = `package svc const svcTemplate = `package svc
import {{.imports}} import {{.imports}}
type ( type ServiceContext struct {
ServiceContext struct {
c config.Config c config.Config
// todo: add your logic here and delete this line }
}
)
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{ return &ServiceContext{

@ -5,9 +5,9 @@ import (
"github.com/tal-tech/go-zero/tools/goctl/util/console" "github.com/tal-tech/go-zero/tools/goctl/util/console"
) )
var rpcTemplateText = `syntax = "proto3"; const rpcTemplateText = `syntax = "proto3";
package remoteuser; package remote;
message Request { message Request {
string username = 1; string username = 1;
@ -19,16 +19,15 @@ message Response {
string gender = 2; string gender = 2;
} }
service User{ service User {
rpc Login(Request)returns(Response); rpc Login(Request) returns(Response);
}` }
`
type ( type rpcTemplate struct {
rpcTemplate struct {
out string out string
console.Console console.Console
} }
)
func NewRpcTemplate(out string, idea bool) *rpcTemplate { func NewRpcTemplate(out string, idea bool) *rpcTemplate {
return &rpcTemplate{ return &rpcTemplate{

@ -1,34 +0,0 @@
package gogen
import (
"fmt"
"path/filepath"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
var etcTemplate = `{
"Name": "{{.serviceName}}.rpc",
"Log": {
"Mode": "console"
},
"ListenOn": "127.0.0.1:8080",
"Etcd": {
"Hosts": ["127.0.0.1:6379"],
"Key": "{{.serviceName}}.rpc"
}
}
`
func (g *defaultRpcGenerator) genEtc() error {
etdDir := g.dirM[dirEtc]
fileName := filepath.Join(etdDir, fmt.Sprintf("%v.json", g.Ctx.ServiceName.Lower()))
if util.FileExists(fileName) {
return nil
}
return util.With("etc").
Parse(etcTemplate).
SaveTo(map[string]interface{}{
"serviceName": g.Ctx.ServiceName.Lower(),
}, fileName, false)
}

@ -435,7 +435,7 @@ func (a *PbAst) GenTypesCode() (string, error) {
types = append(types, structCode) types = append(types, structCode)
} }
buffer, err := util.With("type").Parse(typeTemplate).Execute(map[string]interface{}{ buffer, err := util.With("type").Parse(typeTemplate).Execute(map[string]interface{}{
"types": strings.Join(types, "\n"), "types": strings.Join(types, "\n\n"),
}) })
if err != nil { if err != nil {
return "", err return "", err

@ -1,6 +1,6 @@
package util package util
var headTemplate = `// Code generated by goctl. DO NOT EDIT. var headTemplate = `// Code generated by goctl. DO NOT EDIT!
// Source: {{.source}}` // Source: {{.source}}`
func GetHead(source string) string { func GetHead(source string) string {

Loading…
Cancel
Save