Commit 16a7d991 by 孙龙

up

parent 5d285f9e
......@@ -3,3 +3,20 @@
go run main.go --help
GLOBAL OPTIONS:
-f value 接收的文件 目前暂未使用
* -o value 项目生成的目录 output dir eg : ./ ./output
* -p value 项目包名 go mod init xxx
* -m value 模块名称 model name eg : crm_sendmsg order_sync
* -c 客户端
* -s 服务端
--pre value prefix of package
-i value import proto file, Specify the proto file in which for proto file imports.May be specified multiple times
--proto_path value Specify the directory in which to search for imports. May be specified multiple times
--help, -h show help
--version, -v print the version
#生成服务端代码
go run main.go -s -o=./output -p=go_generator_demo -m=crm_sendmsg
......@@ -52,7 +52,6 @@ func (d *BootGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData)
func (d *BootGenerator) render(file *os.File, data string, templateDataParams *bootTemplateData) (err error) {
t := template.New("main").Funcs(templateFuncMap)
fmt.Println(data)
t, err = t.Parse(data)
if err != nil {
return
......
package generator
import (
"errors"
"fmt"
"github.com/syyongx/php2go"
"go_generator/tools"
"io"
"os"
"path/filepath"
"strings"
)
type ConfigGenerator struct {
}
/**
* 拷贝文件夹,同时拷贝文件夹中的文件
* @param srcPath 需要拷贝的文件夹路径: D:/test
* @param destPath 拷贝到的位置: D:/backup/
*/
func CopyDir(srcPath string, destPath string) error {
//检测目录正确性
if srcInfo, err := os.Stat(srcPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !srcInfo.IsDir() {
e := errors.New("srcPath不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
if destInfo, err := os.Stat(destPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !destInfo.IsDir() {
e := errors.New("destInfo不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
//加上拷贝时间:不用可以去掉
//destPath = destPath + "_" + time.Now().Format("20060102150405")
err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if !f.IsDir() {
path := strings.Replace(path, "\\", "/", -1)
//fmt.Println(path)
pos := php2go.Strrpos(path,"/",-1)
posU := uint(pos) + 1
copyFilename := php2go.Substr(path,posU,-1)
destNewPath := strings.Replace(path, srcPath, destPath, -1)
destNewPath = destPath+copyFilename
//fmt.Println(destNewPath)
fmt.Println("复制文件:" + path + " 到 " + destNewPath)
_,_ = copyFile(path, destNewPath)
}
return nil
})
if err != nil {
fmt.Printf(err.Error())
}
return err
}
//生成目录并拷贝文件
func copyFile(src, dest string) (w int64, err error) {
srcFile, err := os.Open(src)
if err != nil {
fmt.Println(err.Error())
return
}
defer srcFile.Close()
//分割path目录
destSplitPathDirs := strings.Split(dest, "/")
//检测时候存在目录
destSplitPath := ""
for index, dir := range destSplitPathDirs {
if index < len(destSplitPathDirs)-1 {
destSplitPath = destSplitPath + dir + "/"
b, _ := pathExists(destSplitPath)
if b == false {
fmt.Println("创建目录:" + destSplitPath)
//创建目录
err := os.Mkdir(destSplitPath, os.ModePerm)
if err != nil {
fmt.Println(err)
}
}
}
}
dstFile, err := os.Create(dest)
if err != nil {
fmt.Println(err.Error())
return
}
defer dstFile.Close()
return io.Copy(dstFile, srcFile)
}
//检测文件夹路径时候存在
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func (d *ConfigGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
err = CopyDir("./generator/configTemplate/",opt.Output+"/config/dev/")
......
package generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
"text/template"
)
type DaoGenerator struct {
}
type daoTemplateData struct {
OptObj *tools.Option
}
func (d *DaoGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
templateDataParams := &daoTemplateData{
OptObj:opt,
}
directoryPath := path.Join(opt.Output,"/app/dao/"+opt.ModelName+"/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
filename := path.Join(opt.Output,"/app/dao/"+opt.ModelName+"/", "dao.go")
exist := tools.IsFileExist(filename)
if exist {
return
}
//fmt.Println(filename)
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
fmt.Printf("open file:%s failed, err:%v\n", filename, err)
return
}
defer func() {
_ = file.Close()
}()
err = d.render(file, dao_template, templateDataParams)
if err != nil {
fmt.Printf("render failed, err:%v\n", err)
return
}
return
}
func (d *DaoGenerator) render(file *os.File, data string, templateDataParams *daoTemplateData) (err error) {
t := template.New("dao").Funcs(templateFuncMap)
t, err = t.Parse(data)
if err != nil {
return
}
err = t.Execute(file, templateDataParams)
return
}
func init() {
daoGen := &DaoGenerator{}
_ = tools.RegisterServerGenerator("dao generator", daoGen)
}
\ No newline at end of file
package generator
var dao_template = `package {{.OptObj.ModelName}}
import (
{{.OptObj.ModelName}} "golang-asynctask/app/common/config/{{.OptObj.ModelName}}"
"sync"
"time"
"xorm.io/xorm"
"github.com/go-redis/redis/v7"
_ "github.com/go-sql-driver/mysql"
"github.com/ichunt2019/cfg/lib"
redisPool "github.com/ichunt2019/go-redis-pool"
)
var (
once sync.Once
Dao *dao
)
type dao struct {
db map[string]*xorm.Engine //非主从mysql数据库 连接池
dbGroup map[string]*xorm.EngineGroup //mysql主从 连接池
redisGroup map[string]*redisPool.Pool //redis 主从 连接池
}
//获取db实例
func (self *dao) GetDb(databases string) *xorm.Engine {
return self.db[databases]
}
//获取主从db实例
//获取主从db实例
//func (self *dao) GetDbGroup(databases string) *xorm.EngineGroup {
// return self.dbGroup[databases]
//}
//获取主从db实例
//func (self *dao) GetRedisDbGroup(databases string) *redisPool.Pool {
// return self.redisGroup[databases]
//}
func mysqlSetup(d *dao) *dao {
var (
err error
)
DatabaseList := {{.OptObj.ModelName}}.BuildDatabaseList()
GroupDatabaseList := {{.OptObj.ModelName}}.BuildGroupDatabaseList()
if len(DatabaseList) > 0 {
for conName, db := range DatabaseList {
d.db[conName], err = xorm.NewEngine("mysql", db.DataSourceName)
if err != nil {
panic(err)
}
//日志打印SQL
ShowSql := lib.Instance("db").GetBool("xorm.ShowSQL")
d.db[conName].ShowSQL(ShowSql)
//设置连接池的空闲数大小
d.db[conName].SetMaxIdleConns(db.MaxIdleCons)
//设置最大打开连接数
d.db[conName].SetMaxOpenConns(db.MaxOpenCons)
}
}
if len(GroupDatabaseList) > 0 {
for conName, db := range GroupDatabaseList {
d.dbGroup[conName], err = xorm.NewEngineGroup("mysql", db.DataSourceName)
if err != nil {
panic(err)
}
//日志打印SQL
ShowSql := lib.Instance("db").GetBool("xorm.ShowSQL")
d.dbGroup[conName].ShowSQL(ShowSql)
//设置连接池的空闲数大小
d.dbGroup[conName].SetMaxIdleConns(db.MaxIdleCons)
//设置最大打开连接数
d.dbGroup[conName].SetMaxOpenConns(db.MaxOpenCons)
}
}
return d
}
func redisSetup(d *dao) *dao {
var err error
redisGroupList := {{.OptObj.ModelName}}.BuildRedisGroupConfigs()
//fmt.Println(redisGroupList)
for redisServerName, redisInfo := range redisGroupList {
d.redisGroup[redisServerName], err = redisPool.NewHA(&redisPool.HAConfig{
Master: redisInfo.MasterHost,
Slaves: redisInfo.SlaveHost,
Password: redisInfo.Password,
ReadonlyPassword: redisInfo.ReadonlyPassword,
Options: &redis.Options{
DialTimeout: redisInfo.DialTimeout, //连接超时
MinIdleConns: redisInfo.MinIdleConns, //空闲链接数
ReadTimeout: redisInfo.ReadTimeout,
WriteTimeout: redisInfo.WriteTimeout,
},
AutoEjectHost: true,//是否弹出故障主机
ServerFailureLimit: 3,//达到失败次数时弹出
ServerRetryTimeout: 5 * time.Second,//在ServerRetryTimeout之后重试弹出的主机
MinServerNum: 0,//保留min服务器 针对从服务器
})
if err != nil {
panic(err)
}
}
return d
}
func Init() {
Dao = &dao{}
once.Do(func() {
//单、主数据 master
Dao.db = make(map[string]*xorm.Engine, 0)
////主从数据 master slave
//Dao.dbGroup = make(map[string]*xorm.EngineGroup, 0)
////redis连接池 支持主从 master slave
//Dao.redisGroup = make(map[string]*redisPool.Pool, 0)
Dao = mysqlSetup(Dao)
//Dao = redisSetup(Dao)
})
}
`
package lib
import (
"bytes"
"crypto/md5"
"encoding/binary"
"encoding/hex"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"net/url"
"os"
"regexp"
"strings"
"time"
)
var TimeLocation *time.Location
var TimeFormat = "2006-01-02 15:04:05"
var DateFormat = "2006-01-02"
var LocalIP = net.ParseIP("127.0.0.1")
func HttpGET( urlString string, urlParams url.Values, msTimeout int, header http.Header) (*http.Response, []byte, error) {
client := http.Client{
Timeout: time.Duration(msTimeout) * time.Millisecond,
}
urlString = AddGetDataToUrl(urlString, urlParams)
req, err := http.NewRequest("GET", urlString, nil)
if err != nil {
return nil, nil, err
}
if len(header) > 0 {
req.Header = header
}
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}
return resp, body, nil
}
func HttpPOST(urlString string, urlParams url.Values, msTimeout int, header http.Header, contextType string) (*http.Response, []byte, error) {
client := http.Client{
Timeout: time.Duration(msTimeout) * time.Millisecond,
}
if contextType == "" {
contextType = "application/x-www-form-urlencoded"
}
urlParamEncode := urlParams.Encode()
req, err := http.NewRequest("POST", urlString, strings.NewReader(urlParamEncode))
if len(header) > 0 {
req.Header = header
}
req.Header.Set("Content-Type", contextType)
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}
return resp, body, nil
}
func HttpJSON(urlString string, jsonContent string, msTimeout int, header http.Header) (*http.Response, []byte, error) {
client := http.Client{
Timeout: time.Duration(msTimeout) * time.Millisecond,
}
req, err := http.NewRequest("POST", urlString, strings.NewReader(jsonContent))
if len(header) > 0 {
req.Header = header
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}
return resp, body, nil
}
func AddGetDataToUrl(urlString string, data url.Values) string {
if strings.Contains(urlString, "?") {
urlString = urlString + "&"
} else {
urlString = urlString + "?"
}
return fmt.Sprintf("%s%s", urlString, data.Encode())
}
func GetMd5Hash(text string) string {
hasher := md5.New()
hasher.Write([]byte(text))
return hex.EncodeToString(hasher.Sum(nil))
}
func Encode(data string) (string, error) {
h := md5.New()
_, err := h.Write([]byte(data))
if err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}
func ParseServerAddr(serverAddr string) (host, port string) {
serverInfo := strings.Split(serverAddr, ":")
if len(serverInfo) == 2 {
host = serverInfo[0]
port = serverInfo[1]
} else {
host = serverAddr
port = ""
}
return host, port
}
func NewSpanId() string {
timestamp := uint32(time.Now().Unix())
ipToLong := binary.BigEndian.Uint32(LocalIP.To4())
b := bytes.Buffer{}
b.WriteString(fmt.Sprintf("%08x", ipToLong^timestamp))
b.WriteString(fmt.Sprintf("%08x", rand.Int31()))
return b.String()
}
func GetTraceId() (traceId string) {
return calcTraceId(LocalIP.String())
}
func calcTraceId(ip string) (traceId string) {
now := time.Now()
timestamp := uint32(now.Unix())
timeNano := now.UnixNano()
pid := os.Getpid()
b := bytes.Buffer{}
netIP := net.ParseIP(ip)
if netIP == nil {
b.WriteString("00000000")
} else {
b.WriteString(hex.EncodeToString(netIP.To4()))
}
b.WriteString(fmt.Sprintf("%08x", timestamp&0xffffffff))
b.WriteString(fmt.Sprintf("%04x", timeNano&0xffff))
b.WriteString(fmt.Sprintf("%04x", pid&0xffff))
b.WriteString(fmt.Sprintf("%06x", rand.Int31n(1<<24)))
b.WriteString("b0") // 末两位标记来源,b0为go
return b.String()
}
func GetLocalIPs() (ips []net.IP) {
interfaceAddr, err := net.InterfaceAddrs()
if err != nil {
return nil
}
for _, address := range interfaceAddr {
ipNet, isValidIpNet := address.(*net.IPNet)
if isValidIpNet && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
ips = append(ips, ipNet.IP)
}
}
}
return ips
}
func InArrayString(s string, arr []string) bool {
for _, i := range arr {
if i == s {
return true
}
}
return false
}
//Substr 字符串的截取
func Substr(str string, start int64, end int64) string {
length := int64(len(str))
if start < 0 || start > length {
return ""
}
if end < 0 {
return ""
}
if end > length {
end = length
}
return string(str[start:end])
}
//利用正则表达式压缩字符串,去除空格或制表符
func CompressStr(str string) string {
if str == "" {
return ""
}
//匹配一个或多个空白符的正则表达式
reg := regexp.MustCompile("\\s+")
return reg.ReplaceAllString(str, "")
}
func ClientIP(r *http.Request) string {
xForwardedFor := r.Header.Get("X-Forwarded-For")
ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
if ip != "" {
return ip
}
ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
if ip != "" {
return ip
}
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
return ip
}
return ""
}
\ No newline at end of file
package generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
)
type UntilLibFuncGenerator struct {
}
func (d *UntilLibFuncGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
directoryPath := path.Join(opt.Output,"/until/lib/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
err = CopyDir("./generator/untilLibFuncTemplate/",directoryPath+"/")
if err == nil {
fmt.Printf("完成拷贝,Done\n")
}else{
fmt.Printf("未完成拷贝,错误=%v\n",err)
}
return
}
func (d *UntilLibFuncGenerator) render(file *os.File, data string, metaData *tools.ServiceMetaData) (err error) {
return
}
func init() {
unctillibGen := &UntilLibFuncGenerator{}
_ = tools.RegisterServerGenerator("unctillibfunc generator", unctillibGen)
}
\ No newline at end of file
......@@ -2,7 +2,12 @@ package generator
import (
"bytes"
"errors"
"fmt"
"github.com/syyongx/php2go"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"unicode"
......@@ -45,3 +50,110 @@ func ToUnderScoreString(name string) string {
return buffer.String()
}
/**
* 拷贝文件夹,同时拷贝文件夹中的文件
* @param srcPath 需要拷贝的文件夹路径: D:/test
* @param destPath 拷贝到的位置: D:/backup/
*/
func CopyDir(srcPath string, destPath string) error {
//检测目录正确性
if srcInfo, err := os.Stat(srcPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !srcInfo.IsDir() {
e := errors.New("srcPath不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
if destInfo, err := os.Stat(destPath); err != nil {
fmt.Println(err.Error())
return err
} else {
if !destInfo.IsDir() {
e := errors.New("destInfo不是一个正确的目录!")
fmt.Println(e.Error())
return e
}
}
//加上拷贝时间:不用可以去掉
//destPath = destPath + "_" + time.Now().Format("20060102150405")
err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if !f.IsDir() {
path := strings.Replace(path, "\\", "/", -1)
//fmt.Println(path)
pos := php2go.Strrpos(path,"/",-1)
posU := uint(pos) + 1
copyFilename := php2go.Substr(path,posU,-1)
destNewPath := strings.Replace(path, srcPath, destPath, -1)
destNewPath = destPath+copyFilename
//fmt.Println(destNewPath)
fmt.Println("复制文件:" + path + " 到 " + destNewPath)
_,_ = copyFile(path, destNewPath)
}
return nil
})
if err != nil {
fmt.Printf(err.Error())
}
return err
}
//生成目录并拷贝文件
func copyFile(src, dest string) (w int64, err error) {
srcFile, err := os.Open(src)
if err != nil {
fmt.Println(err.Error())
return
}
defer srcFile.Close()
//分割path目录
destSplitPathDirs := strings.Split(dest, "/")
//检测时候存在目录
destSplitPath := ""
for index, dir := range destSplitPathDirs {
if index < len(destSplitPathDirs)-1 {
destSplitPath = destSplitPath + dir + "/"
b, _ := pathExists(destSplitPath)
if b == false {
fmt.Println("创建目录:" + destSplitPath)
//创建目录
err := os.Mkdir(destSplitPath, os.ModePerm)
if err != nil {
fmt.Println(err)
}
}
}
}
dstFile, err := os.Create(dest)
if err != nil {
fmt.Println(err.Error())
return
}
defer dstFile.Close()
return io.Copy(dstFile, srcFile)
}
//检测文件夹路径时候存在
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
......@@ -23,6 +23,8 @@ var AllDirList []string = []string{
"config/dev",
"config/prod",
"logs",
"until",
"until/lib",
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment