Commit 31bdf238 by 孙龙

up

parent b162fb9b
......@@ -28,5 +28,10 @@ GLOBAL OPTIONS:
#生成服务端代码
cd ./scaffold
go run main.go -s -o=框架代码生成目录 -p=go-mod-init包名 -m=模块名
go run main.go -s -o=./output -p=go_generator_demo -m=crm_sendmsg
# golang-generator 框架代码生成器(脚手架)
go run main.go --help
GLOBAL OPTIONS:
-o value 项目生成的目录 output dir eg : ./ ./output
-p value 项目包名 go mod init xxx
-m value 模块名称 model name eg : crm_sendmsg order_sync
-c 客户端
-s 服务端
-f value 接收的文件 目前暂未使用
--pre value prefix of package
--help, -h show help
--version, -v print the version
#生成服务端代码
cd ./scaffold
go run main.go -s -o=../output -p=go_generator_demo -m=crm_sendmsg
package crm_comuser
import (
"github.com/ichunt2019/cfg/lib"
)
type BaseDatabase struct {
DataSourceName string
MaxIdleCons int
MaxOpenCons int
Prefix string
}
type GroupDatabase struct {
DataSourceName []string
MaxIdleCons int
MaxOpenCons int
Prefix string
}
//单、主数据 master
func BuildDatabaseList() (DatabaseList map[string]BaseDatabase) {
return map[string]BaseDatabase{
"crm": {
DataSourceName: lib.Instance("db").GetString("crm.data_source_name"),
Prefix: lib.Instance("db").GetString("crm.table_prefix"),
MaxIdleCons:lib.Instance("db").GetInt("crm.max_idle_conn"),
MaxOpenCons:lib.Instance("db").GetInt("crm.max_open_conn"),
},
}
}
//主从数据 master slave
func BuildGroupDatabaseList() (DatabaseList map[string]GroupDatabase) {
return map[string]GroupDatabase{
//"liexin": {
// DataSourceName:lib.Instance("db").GetStringSlice("liexin.data_source_name"),
// Prefix: lib.Instance("db").GetString("liexin.table_prefix"),
// MaxIdleCons:lib.Instance("db").GetInt("liexin.max_idle_conn"),
// MaxOpenCons:lib.Instance("db").GetInt("liexin.max_open_conn"),
//},
}
}
package crm_comuser
import (
"github.com/ichunt2019/cfg/lib"
"time"
)
type RedisGroupDatabase struct {
MasterHost string
Password string //master密码
SlaveHost []string
ReadonlyPassword string //从服务器密码
DialTimeout time.Duration //连接超时
MinIdleConns int //空间链接
ReadTimeout time.Duration //读超时
WriteTimeout time.Duration //写超时
}
//多数据库配置
func BuildRedisGroupConfigs() ( map[string]RedisGroupDatabase) {
//fmt.Println("6666666666")
//fmt.Println(lib.Instance("redis").GetStringSlice("api.slave.host"))
return map[string]RedisGroupDatabase{
"api": {
MasterHost: lib.Instance("redis").GetString("api.master.host"),
Password:lib.Instance("redis").GetString("api.master.password"),
SlaveHost: lib.Instance("redis").GetStringSlice("api.slave.host"),
ReadonlyPassword:lib.Instance("redis").GetString("api.slave.password"),
DialTimeout: time.Duration(lib.Instance("redis").GetInt("api.dial_timeout"))*time.Second,
ReadTimeout: time.Duration(lib.Instance("redis").GetInt("api.read_timeout"))*time.Second,
WriteTimeout: time.Duration(lib.Instance("redis").GetInt("api.write_timeout"))*time.Second,
MinIdleConns:lib.Instance("redis").GetInt("api.min_idle_conns"),
},
"sku": {
MasterHost: lib.Instance("redis").GetString("sku.master.host"),
Password:lib.Instance("redis").GetString("sku.master.password"),
SlaveHost: lib.Instance("redis").GetStringSlice("sku.slave.host"),
ReadonlyPassword:lib.Instance("redis").GetString("sku.slave.password"),
DialTimeout: time.Duration(lib.Instance("redis").GetInt("sku.dial_timeout"))*time.Second,
ReadTimeout: time.Duration(lib.Instance("redis").GetInt("sku.read_timeout"))*time.Second,
WriteTimeout: time.Duration(lib.Instance("redis").GetInt("sku.write_timeout"))*time.Second,
MinIdleConns:lib.Instance("redis").GetInt("sku.min_idle_conns"),
},
}
}
package generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
"text/template"
)
type BootGenerator struct {
}
type bootTemplateData struct {
OptObj *tools.Option
}
func (d *BootGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
filename := path.Join(opt.Output,"/boot/"+opt.ModelName+"/", "boot.go")
if IsFileExist(filename){
return nil
}
templateDataParams := &bootTemplateData{
OptObj:opt,
}
directoryPath := path.Join(opt.Output,"/boot/"+opt.ModelName+"/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
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, boot_template, templateDataParams)
if err != nil {
fmt.Printf("render failed, err:%v\n", err)
return
}
return
}
func (d *BootGenerator) render(file *os.File, data string, templateDataParams *bootTemplateData) (err error) {
t := template.New("main").Funcs(templateFuncMap)
t, err = t.Parse(data)
if err != nil {
return
}
err = t.Execute(file, templateDataParams)
return
}
func init() {
bootGen := &BootGenerator{}
_ = tools.RegisterServerGenerator("Boot generator", bootGen)
}
\ No newline at end of file
package generator
var boot_template = `package boot
import (
"github.com/ichunt2019/cfg/lib"
{{.OptObj.ModelName}} "golang-asynctask/app/dao/{{.OptObj.ModelName}}"
xlog "github.com/ichunt2019/lxLog/log"
)
func Init(configPath string,logPath string)(err error){
err = lib.Init(configPath)
if err != nil{
panic(err)
}
xlog.Init(logPath,"{{.OptObj.ModelName}}")
//初始化数据库
{{.OptObj.ModelName}}.Init()
return
}
`
title = "TOML 例子"
viewpath = "/home/www/templates/"
pushErpDomain = "http://crm.liexin.net/api/pushComUserRelationToErp"
crmSendMsgByconflictSale = "http://crm.liexin.net/api/sendMsgByconflictSale"
sendMsgByChangeInvoiceCom = "http://crm.liexin.net/api/sendMsgByChangeInvoiceCom"
apiKey = "crm a1b2c3d4e5f6g7h8i9jk"
#crm发送备忘录提醒
crmDomain = "http://crm.liexin.net/"
ichuntapiDomain = "http://api.liexin.com"
#异步任务转发url
asyncTaskforward = "http://192.168.1.168:8700/callback"
#推送云芯 微信用户信息
pushWechatYunXinApi = "http://cloud.liexindev.net/inner/oauth/resetopenid"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # 日期时间是一等公民。为什么不呢?
[rabbitmq_crm_comuser_fenfa]
queue_name="a-maxwell"
routing_key="maxwell.lie_invoice_company"
exchange=""
type="direct"
dns="amqp://guest:guest@192.168.2.232:5672/"
[rabbitmq_crm_comuser]
queue_name="crm_comusertoerp"
routing_key="crm_comusertoerp"
exchange=""
type="direct"
dns="amqp://guest:guest@192.168.2.232:5672/"
[rabbitmq_crm_invoice_com_apply]
queue_name="crm_invoice_com_apply"
routing_key="crm_invoice_com_apply"
exchange=""
type="direct"
dns="amqp://guest:guest@192.168.2.232:5672/"
[rabbitmq_ichunt_wechat_focus]
queue_name="szichunt_wechat_userinfo"
routing_key="szichunt_wechat_userinfo"
exchange=""
type="direct"
dns="amqp://guest:guest@192.168.2.232:5672/"
[servers]
# 你可以依照你的意愿缩进。使用空格或Tab。TOML不会在意。
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [["gamma", "delta"],[1, 2]]
[database]
[database.default]
host = "192.168.2.246"
[supplier_no_brand]
3 = [615,757,46596,43172,52,46481,47811,48817]
7 = [47778]
9 = [47778,4589,12369]
[xorm]
ShowSQL = true
[crm]
data_source_name = "liexin_crm:liexin_crm#zsyM@tcp(192.168.1.235:3306)/liexin_crm?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
max_open_conn = 0
max_idle_conn = 0
table_prefix = "lie_"
max_conn_life_time = 100
[cms]
data_source_name = "ichuntcms:ichuntcms#zsyM@tcp(192.168.1.252:3306)/ichuntcms?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
max_open_conn = 0
max_idle_conn = 0
table_prefix = "lie_"
max_conn_life_time = 100
[liexin]
data_source_name = "liexin:liexin#zsyM@tcp(192.168.2.252:3306)/liexin?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
max_open_conn = 0
max_idle_conn = 0
table_prefix = "lie_"
max_conn_life_time = 100
[liexin_demo]
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
data_source_name = [
"micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing",
"micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing",
"micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing",
]
[micro_service]
dns = "micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing"
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
[sku]
[sku.sku_0]
dns = "micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing"
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
[sku.sku_1]
dns = "micro_service:lie_micro_service#zsyM@tcp(192.168.2.252:3306)/lie_micro_service?charset=utf8&parseTime=true&loc=Asia%2FChongqing"
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
[dashboard]
dns = "dashboard:dashboard#zsyM@tcp(192.168.1.235:3306)/dashboard?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
[scm_data]
dns = "liexin_scm_data:scm_data@tcp(192.168.1.235:3306)/liexin_scm_data?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
max_open_conn = 20
max_idle_conn = 10
table_prefix = ""
max_conn_life_time = 100
#服务注册名称
micro_service_name = "golang_common_demo"
#etcd配置信息 etcd服务的ip端口用户密码
[etcd_config]
addrs = [
"192.168.2.232:2379"
]
username = ""
password = ""
#注册到etcd中的ip 端口 权重信息
[etcd_regist]
ip = "192.168.2.246"
port = 60020
weight = 10
[base]
debug_mode="debug"
time_location="Asia/Chongqing"
[http]
addr ="192.168.2.246:8700" # 监听地址, default ":8700"
read_timeout = 10 # 读取超时时长
write_timeout = 10 # 写入超时时长
max_header_bytes = 20 # 最大的header大小,二进制位长度
[api]
dial_timeout = 20
min_idle_conns = 10
read_timeout = 10
write_timeout = 10
[api.master]
host = "192.168.1.235:6379"
password = "icDb29mLy2s"
[api.slave]
password = "icDb29mLy2s"
host = [
"192.168.1.235:6379",
"192.168.1.237:6379",
]
[sku]
dial_timeout = 20
min_idle_conns = 10
read_timeout = 10
write_timeout = 10
[sku.master]
host = "192.168.1.235:6379"
password = "icDb29mLy2s"
[sku.slave]
password = "icDb29mLy2s"
host = [
"192.168.1.235:6379",
"192.168.1.237:6379",
]
package generator
import (
"fmt"
"go_generator/tools"
"os"
)
type ConfigGenerator struct {
}
func (d *ConfigGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
err = CopyDir("./generator/configTemplate/",opt.Output+"/config/dev/")
if err == nil {
fmt.Printf("完成拷贝,Done\n")
}else{
fmt.Printf("未完成拷贝,错误=%v\n",err)
}
return
}
func (d *ConfigGenerator) render(file *os.File, data string, metaData *tools.ServiceMetaData) (err error) {
return
}
func init() {
configGen := &ConfigGenerator{}
_ = tools.RegisterServerGenerator("config generator", configGen)
}
\ No newline at end of file
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){
filename := path.Join(opt.Output,"/app/dao/"+opt.ModelName+"/", "dao.go")
if IsFileExist(filename){
return nil
}
templateDataParams := &daoTemplateData{
OptObj:opt,
}
directoryPath := path.Join(opt.Output,"/app/dao/"+opt.ModelName+"/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
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 generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
)
type DatabasesConfGenerator struct {
}
func (d *DatabasesConfGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
directoryPath := path.Join(opt.Output,"/app/common/config/",opt.ModelName,"/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
err = CopyDir("./generator/appComConfTemplate/",directoryPath+"/")
if err == nil {
fmt.Printf("完成拷贝,Done\n")
}else{
fmt.Printf("未完成拷贝,错误=%v\n",err)
}
return
}
func (d *DatabasesConfGenerator) render(file *os.File, data string, metaData *tools.ServiceMetaData) (err error) {
return
}
func init() {
configGen := &DatabasesConfGenerator{}
_ = tools.RegisterServerGenerator("appcommonconfig generator", configGen)
}
\ No newline at end of file
package generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
"text/template"
)
type GoModGenerator struct {
}
type gomodTemplateData struct {
OptObj *tools.Option
}
func (d *GoModGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
filename := path.Join(opt.Output,"/", "go.mod")
if IsFileExist(filename){
return nil
}
templateDataParams := &gomodTemplateData{
OptObj:opt,
}
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, gomod_template, templateDataParams)
if err != nil {
fmt.Printf("render failed, err:%v\n", err)
return
}
return
}
func (d *GoModGenerator) render(file *os.File, data string, templateDataParams *gomodTemplateData) (err error) {
t := template.New("gomod").Funcs(templateFuncMap)
t, err = t.Parse(data)
if err != nil {
return
}
err = t.Execute(file, templateDataParams)
return
}
func init() {
gomodGen := &GoModGenerator{}
_ = tools.RegisterServerGenerator("gomod generator", gomodGen)
}
\ No newline at end of file
package generator
var gomod_template = `module {{.OptObj.PackageName}}
go 1.14
`
package generator
import (
"fmt"
"go_generator/tools"
"os"
"path"
"text/template"
)
type MainGenerator struct {
}
type templateData struct {
OptObj *tools.Option
}
func (d *MainGenerator) Run(opt *tools.Option,metaData *tools.ServiceMetaData) (err error){
filename := path.Join(opt.Output,"/cmd/"+opt.ModelName+"/", "main.go")
if IsFileExist(filename){
return nil
}
templateDataParams := &templateData{
OptObj:opt,
}
directoryPath := path.Join(opt.Output,"/cmd/"+opt.ModelName+"/");
err = tools.CreateMutiDir(directoryPath)
if(err != nil){
panic(err)
}
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, main_template, templateDataParams)
if err != nil {
fmt.Printf("render failed, err:%v\n", err)
return
}
return
}
func (d *MainGenerator) render(file *os.File, data string, templateDataParams *templateData) (err error) {
t := template.New("main").Funcs(templateFuncMap)
//fmt.Println(data)
t, err = t.Parse(data)
if err != nil {
return
}
err = t.Execute(file, templateDataParams)
return
}
func init() {
mainGen := &MainGenerator{}
_ = tools.RegisterServerGenerator("main generator", mainGen)
}
\ No newline at end of file
package generator
var main_template = `package main
import (
"flag"
xlog "github.com/ichunt2019/lxLog/log"
"{{.OptObj.PackageName}}/app/service/{{.OptObj.ModelName}}"
boot "{{.OptObj.PackageName}}/boot/{{.OptObj.ModelName}}"
)
var (
configPath string
logPath string
action string
)
//crm释放任务 小组池
func main(){
defer func(){
xlog.Instance("{{.OptObj.ModelName}}").Close()
}()
flag.StringVar(&configPath, "config", "./config/dev/", "配置文件")
flag.StringVar(&logPath, "logdir", "./logs/", "日志文件存储目录")
flag.Parse()
_ = boot.Init(configPath,logPath)
{{.OptObj.ModelName}}.RemindTimeout()
}
`
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
package generator
import (
"bytes"
"errors"
"fmt"
"github.com/syyongx/php2go"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"unicode"
)
var templateFuncMap = template.FuncMap{
"Capitalize": Capitalize,
}
func IsFileExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}
func Capitalize(str string) string {
var output string
chars := []rune(str)
for i := 0; i < len(chars); i++ {
if i == 0 {
if chars[i] < 'a' || chars[i] > 'z' {
return output
}
output += strings.ToUpper(string(chars[i]))
continue
}
output += string(chars[i])
}
return output
}
func ToUnderScoreString(name string) string {
var buffer bytes.Buffer
for i, r := range name {
if unicode.IsUpper(r) {
if i != 0 {
buffer.WriteString("_")
}
buffer.WriteString(fmt.Sprintf("%c", unicode.ToLower(r)))
} else {
buffer.WriteString(fmt.Sprintf("%c", unicode.ToLower(r)))
}
}
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
}
module go_generator
go 1.14
require (
github.com/syyongx/php2go v0.9.4
github.com/urfave/cli v1.22.5 // indirect
)
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/syyongx/php2go v0.9.4 h1:qUtETTHzqHzxZK8plkbkb0YawD8bpLpxNsbzHQmb22Y=
github.com/syyongx/php2go v0.9.4/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw=
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
package main
import (
"fmt"
"go_generator/tools"
"log"
"os"
"github.com/urfave/cli"
_ "go_generator/generator"
)
func main() {
var opt tools.Option
var importFiles cli.StringSlice
var protoPaths cli.StringSlice
app := cli.NewApp()
app.Version = "2.0.1"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "f",
Usage: "接收的文件 目前暂未使用",
Required: true,
Destination: &opt.Proto3Filename,
},
cli.StringFlag{
Name: "o",
Usage: "项目生成的目录 output dir eg : ./ ./output",
Required: true,
Destination: &opt.Output,
},
cli.StringFlag{
Name: "p",
Usage: "项目包名 go mod init xxx",
Required: true,
Destination: &opt.PackageName,
},
cli.StringFlag{
Name: "m",
Usage: "模块名称 model name eg : crm_sendmsg order_sync",
Required: true,
Destination: &opt.ModelName,
},
cli.BoolFlag{
Name: "c",
Usage: "客户端",
Destination: &opt.GenClientCode,
},
cli.BoolFlag{
Name: "s",
Usage: "服务端",
Destination: &opt.GenServerCode,
},
cli.StringFlag{
Name: "pre",
Value: "",
Usage: "prefix of package",
Destination: &opt.Prefix,
},
cli.StringSliceFlag{
Name: "i",
Usage: "import proto file, Specify the proto file in which for proto file imports.May be specified multiple times",
Value: &importFiles,
},
cli.StringSliceFlag{
Name: "proto_path",
Usage: "Specify the directory in which to search for imports. May be specified multiple times",
Value: &protoPaths,
},
}
app.Action = func(c *cli.Context) error {
//命令行程序代码的入口
err := tools.GenMgr.Run(&opt)
if err != nil {
fmt.Printf("code generator failed, err:%v\n", err)
return err
}
fmt.Println("code generate succ")
return nil
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
set GOLANGOUTPURDIRNAME=%1
set GOLANGPACKNAME=%2
set GOLANGMODELNAME=%3
@echo off
if not defined GOLANGOUTPURDIRNAME (echo "error : The first params is the output directory name")
if not defined GOLANGPACKNAME ( echo "error : The two params is the go mod pack name" )
if not defined GOLANGMODELNAME (echo "error : The three params is the output directory name")
package tools
import (
"fmt"
"os"
)
func IsFileExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}
func CreateMutiDir(filePath string) error {
if !isExist(filePath) {
err := os.MkdirAll(filePath, os.ModePerm)
if err != nil {
fmt.Println("创建文件夹失败,error info:", err)
return err
}
return err
}
return nil
}
// 判断所给路径文件/文件夹是否存在(返回true是存在)
func isExist(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}
\ No newline at end of file
package tools
import (
"fmt"
"os"
"path"
)
var AllDirList []string = []string{
"app",
"app/common",
"app/common/config",
"app/common/const",
"app/common/function",
"app/controller",
"app/dao",
"app/model",
"app/service",
"boot",
"cmd",
"config",
"config/dev",
"config/prod",
"logs",
"until",
"until/lib",
}
var GenMgr *GeneratorMgr = &GeneratorMgr{
genClientMap: make(map[string]Generator),
genServerMap: make(map[string]Generator),
metaData: &ServiceMetaData{},
}
type GeneratorMgr struct {
genClientMap map[string]Generator
genServerMap map[string]Generator
metaData *ServiceMetaData
}
func (g *GeneratorMgr) createAllDir(opt *Option) (err error) {
for _, dir := range AllDirList {
fullDir := path.Join(opt.Output, dir)
err = os.MkdirAll(fullDir, 0755)
if err != nil {
fmt.Printf("mkdir dir %s failed, err:%v\n", dir, err)
return
}
}
return
}
func (g *GeneratorMgr) Run(opt *Option) (err error) {
if opt.GenServerCode {
err = g.createAllDir(opt)
if err != nil {
return
}
for _, gen := range g.genServerMap {
err = gen.Run(opt, g.metaData)
if err != nil {
return
}
}
return
}
return
}
func RegisterClientGenerator(name string, gen Generator) (err error) {
_, ok := GenMgr.genClientMap[name]
if ok {
err = fmt.Errorf("generator %s is exists", name)
return
}
GenMgr.genClientMap[name] = gen
return
}
func RegisterServerGenerator(name string, gen Generator) (err error) {
_, ok := GenMgr.genServerMap[name]
if ok {
err = fmt.Errorf("generator %s is exists", name)
return
}
GenMgr.genServerMap[name] = gen
return
}
package tools
import (
"fmt"
"os/exec"
)
func gomodinit(opt *Option)(err error){
fmt.Println("666")
cmd := exec.Command("go","mod","init","hello world")
res, err := cmd.Output()
fmt.Println(string(res))
// return
return
}
package tools
type Generator interface {
Run(opt *Option, metaData *ServiceMetaData) error
}
type ServiceMetaData struct {
//服务唯一标识,用来服务注册以及发现,用点进行分隔,比如 google.gmail.account.user
ServiceName string
//包名
PackageName string
//import path,值为 go_package="xxx/xx/xxx"
ImportPath string
//是否包含go_package
containGoPackage bool
Prefix string
}
package tools
type Option struct {
Proto3Filename string
Output string
PackageName string
ModelName string
GenClientCode bool
GenServerCode bool
Prefix string
GoPath string
ImportFiles []string
ProtoPaths []string
}
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