go generate 代码生成

这是一个尝试下的代码,实现golang解析注释,然后生成代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
	"fmt"
	"os"
)

//go:generate echo "hello world"
func main____() {
	var (
		pwd string 
	)
	pwd,_ = os.Getwd()
	fmt.Println("当前目录: ",pwd)

}

这里我打算使用这个库

go ast 解析器

我的项目

初步实现代码生成器

代码生成器雏形

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package parseutil

import (
	"fmt"
	aster "github.com/szyhf/go-aster"
	"html/template"
	_ "io/ioutil"
	"os"
	"strings"
)

func ParseWith(path string,inputTableName string ,inputStructName string ) {
	pkgs, err := aster.ParseDir(path, nil)
	if err != nil {
		panic(err)
	}
	for _, pkg := range pkgs {
		var pkgName = pkg.Name
		fmt.Println("pkg name =", pkgName)
		models := pkg.Structs
		for _, model := range models {
			fmt.Println(model.Docs)
			if inputStructName == model.Name {
				generateRepo(model,pkg,path,inputTableName)
			}
			//generateRepo(model,pkg,path)
		}
	}
}
func generateRepo(model *aster.StructType,pkg *aster.PackageType,path string ,inputTableName string ) {

	var (
		modelName string = model.Name
		tableName string = inputTableName
		fseq string
		scanFields string
		packageName string
		fields string
		question string
	)
	packageName = pkg.Name
	var dbFields []string
	var structFields []string
	for _,f := range model.Fields {
		dbname := f.Tag.Get("db")
		if dbname == "" {
			dbname = f.Name
		}
		dbFields = append(dbFields,dbname)
		structFields = append(structFields,f.Name)

	}
	fields  = strings.Join(dbFields,",")
	{
		var arr []string
		for _,f := range dbFields {
			arr = append(arr,fmt.Sprintf("%s = ?",f))
		}
		fseq = strings.Join(arr,",")
		for i,v := range model.Fields {
			name := v.Name
			arr[i] = "&u."+name
		}
		scanFields = strings.Join(arr,",")
		//填充??
		for i,_ := range model.Fields {
			arr[i] = "?"
		}
		question = strings.Join(arr,",")
	}

	//var fileName = fmt.Sprintf("%s/%s_impl.go",path,modelName)
	tpl, err := template.ParseFiles("./template/dao.tpl")
	if err != nil {
		panic(err)
	}
	//f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		panic(err)
	}

	tpl.Execute(os.Stdout,map[string]interface{}{
		"modelName":modelName,
		"tableName":tableName,
		"fseq":fseq,
		"scanFields":template.HTML(scanFields),
		"packageName":packageName,
		"fields":fields,
		"question":question,

	})
	//model.Methods[0].
	// id
	//ioutil.WriteFile(fileName,[]byte("afsa"),0640)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{{ .packageName}}

import (
	"database/sql"
	"fmt"
)

type (
	{{.modelName}}Repo struct {
		db *sql.DB
	}
)

func (w {{.modelName}}Repo) QueryById(input *User) (u *User, err error) {
	var db = w.db
	row := db.QueryRow("select id,name,password from t_user where  = ?", input.ID())

	u = &User{}
	_ = row.Scan({{.scanFields}})

	return u, err
}

func (w {{.modelName}}Repo) QueryAll( ) (res []*User, err error) {
	var db = w.db
	user := &User{}
	rows, err := db.Query(fmt.Sprintf("select id,name,password from %s ", user.TableName()))
	if err != nil {
		return res, err
	}
	defer rows.Close()

	for rows.Next() {
		var u User
		_ = rows.Scan(&u.Id,&u.Name,&u.Password)
		res = append(res, &u)
	}
	return res, err
}

func (w {{.modelName}}Repo) DeleteById(input *User) (int64, error) {
	var db = w.db
	exec, err := db.Exec(fmt.Sprintf("delete from %s where id = ?",input.TableName()), input.ID())
	if err != nil {
		return 0, err
	}
	cnt, err := exec.RowsAffected()
	if err != nil {
		return cnt, err
	}
	return cnt, err
}
func (w {{.modelName}}Repo) UpdateById(u *User) (int64, error) {
	var db = w.db
	exec, err := db.Exec(fmt.Sprintf("update %s  set {{.fseq}}",u.TableName()), {{.scanFields}})
	if err != nil {
		return 0, err
	}
	id, err := exec.LastInsertId()
	u.SetLastInsertId(id)
	cnt, _ := exec.RowsAffected()
	return cnt, nil
}

func (w {{.modelName}}Repo) Insert(u *User) error {
	var db = w.db
	_,err := db.Exec(fmt.Sprintf("insert into %s ({{.fields}})values({{.question}})",u.TableName()),{{.scanFields}})
	return err
}