Compare commits
	
		
			46 Commits
		
	
	
		
			develop
			...
			391e47fe33
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 391e47fe33 | |||
| fa426ae90c | |||
| 39e3cdef91 | |||
| ad8c3dc47d | |||
| 42282e2001 | |||
| 376f3dfb23 | |||
| 275e52a108 | |||
| ffccdeffd4 | |||
| 30059c0341 | |||
| cf210a4514 | |||
| a9a4287650 | |||
| 802c795914 | |||
| 73f4af74f9 | |||
| affaca969e | |||
| 168bb99c65 | |||
| 5e136c1749 | |||
| 0701313fa7 | |||
| 62cdd3570a | |||
| daab8f3bd5 | |||
| 28d9566e07 | |||
| ca74db4587 | |||
| e8ab043be7 | |||
| a212583f41 | |||
| 90cb23d8c9 | |||
| c97a3b3bcb | |||
| 4652955c2a | |||
| 9fcae03b02 | |||
| 64ce45cd0a | |||
| 82f944f28a | |||
| 2c436b1a6c | |||
| a63f196e0b | |||
| cf07d30ca7 | |||
| 6287bc062f | |||
| 98ccd35d19 | |||
| f9fb6a5b4d | |||
| fc605ce397 | |||
| 9f07e2521e | |||
| d424a2fd20 | |||
| 4d83580f69 | |||
| a29a211ee5 | |||
| 911ff18b5a | |||
| d491d147f4 | |||
| 81fb0900df | |||
| a4f6d5af95 | |||
| 43bd254dde | |||
| eaa37708c7 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -6,6 +6,7 @@ | ||||
| *.dll | ||||
| *.so | ||||
| *.dylib | ||||
| *.xlsx | ||||
|  | ||||
| # Test binary, built with `go test -c` | ||||
| *.test | ||||
|  | ||||
							
								
								
									
										30
									
								
								balance/abstract.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								balance/abstract.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| // Package balance... | ||||
| // | ||||
| // Description : balance... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-22 4:45 下午 | ||||
| package balance | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| ) | ||||
|  | ||||
| // IBalance 负载算法接口约束 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:45 下午 2021/11/22 | ||||
| type IBalance interface { | ||||
| 	// GetServerNode 获取一个服务器节点 | ||||
| 	GetServerNode(req *http.Request) (*define.ServerNode, error) | ||||
| 	// AddServerNode 新增一个服务器节点 | ||||
| 	AddServerNode(node *define.ServerNode) error | ||||
| 	// Remove 移除一个节点 | ||||
| 	Remove(hostIP string, port int, force bool) | ||||
| 	// GetServerNodeList 获取服务节点列表 | ||||
| 	GetServerNodeList() []*define.ServerNode | ||||
| } | ||||
| @ -7,7 +7,12 @@ | ||||
| // Date : 2021-10-19 2:26 下午 | ||||
| package balance | ||||
|  | ||||
| import "sync" | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"sync" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| ) | ||||
|  | ||||
| // base ... | ||||
| // | ||||
| @ -16,6 +21,7 @@ import "sync" | ||||
| // Date : 2:26 下午 2021/10/19 | ||||
| type base struct { | ||||
| 	lock      *sync.RWMutex | ||||
| 	severList []*define.ServerNode | ||||
| } | ||||
|  | ||||
| // Lock ... | ||||
| @ -53,3 +59,53 @@ func (b *base) RLock() { | ||||
| func (b *base) RUnlock() { | ||||
| 	b.lock.RUnlock() | ||||
| } | ||||
|  | ||||
| // AddServerNode 新添加一个服务器节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:07 下午 2021/10/20 | ||||
| func (b *base) AddServerNode(node *define.ServerNode) error { | ||||
| 	if len(node.HostIP) == 0 || node.Port <= 0 { | ||||
| 		return errors.New("host ip or port is invalid") | ||||
| 	} | ||||
| 	b.Lock() | ||||
| 	defer b.Unlock() | ||||
| 	for _, item := range b.severList { | ||||
| 		if item.HostIP == node.HostIP && item.Port == node.Port { | ||||
| 			return errors.New("host config is already exist") | ||||
| 		} | ||||
| 	} | ||||
| 	b.severList = append(b.severList, node) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:19 下午 2021/10/20 | ||||
| func (b *base) Remove(hostIP string, port int, force bool) { | ||||
| 	b.Lock() | ||||
| 	defer b.Unlock() | ||||
| 	tmpServerNode := make([]*define.ServerNode, 0) | ||||
| 	for _, item := range b.severList { | ||||
| 		if item.HostIP == hostIP && item.Port == port { | ||||
| 			if force { | ||||
| 				continue | ||||
| 			} | ||||
| 			item.Status = define.ServerNodeStatusRemove | ||||
| 		} | ||||
| 		tmpServerNode = append(tmpServerNode, item) | ||||
| 	} | ||||
| 	b.severList = tmpServerNode | ||||
| } | ||||
|  | ||||
| // GetServerNodeList 获取服务器节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:33 下午 2021/10/20 | ||||
| func (b *base) GetServerNodeList() []*define.ServerNode { | ||||
| 	return b.severList | ||||
| } | ||||
|  | ||||
| @ -16,5 +16,6 @@ type ServerNode struct { | ||||
| 	HostIP        string  `json:"host_ip"`        // 机器IP | ||||
| 	Port          int     `json:"port"`           // 机器端口 | ||||
| 	Status        int     `json:"status"`         // 机器状态 | ||||
| 	Weight int    `json:"weight"`  // 机器权重 | ||||
| 	Weight        float64 `json:"weight"`         // 机器权重 | ||||
| 	CurrentWeight float64 `json:"current_weight"` // 当前权重 | ||||
| } | ||||
|  | ||||
							
								
								
									
										62
									
								
								balance/ip_hash.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								balance/ip_hash.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| // Package balance... | ||||
| // | ||||
| // Description : balance... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-22 4:39 下午 | ||||
| package balance | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/util" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| ) | ||||
|  | ||||
| // NewIPHash ip hash 负载均衡 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:53 下午 2021/11/22 | ||||
| func NewIPHash(severList []*define.ServerNode) (IBalance, error) { | ||||
| 	if nil == severList || len(severList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	return &IPHash{ | ||||
| 		base: base{ | ||||
| 			lock:      &sync.RWMutex{}, | ||||
| 			severList: severList, | ||||
| 		}, | ||||
| 		serverList: severList, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // IPHash ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:57 下午 2021/11/22 | ||||
| type IPHash struct { | ||||
| 	base | ||||
| 	serverList []*define.ServerNode | ||||
| } | ||||
|  | ||||
| // GetServerNode ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:53 下午 2021/11/22 | ||||
| func (ih *IPHash) GetServerNode(req *http.Request) (*define.ServerNode, error) { | ||||
| 	clintIPHashID := util.GetHashID(util.GetRemoteIp(req)) | ||||
| 	ih.RLock() | ||||
| 	defer ih.RUnlock() | ||||
| 	if len(ih.serverList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	return ih.serverList[int(clintIPHashID%uint64(len(ih.serverList)))], nil | ||||
| } | ||||
| @ -8,6 +8,7 @@ | ||||
| package balance | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| @ -19,15 +20,15 @@ import ( | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:40 下午 2021/10/19 | ||||
| func NewPoll(serverList []*define.ServerNode) (*Poll, error) { | ||||
| func NewPoll(serverList []*define.ServerNode) (IBalance, error) { | ||||
| 	if nil == serverList || len(serverList) == 0 { | ||||
| 		return nil, errors.New("server list is empty") | ||||
| 	} | ||||
| 	return &Poll{ | ||||
| 		base: base{ | ||||
| 			lock:      &sync.RWMutex{}, | ||||
| 			severList: serverList, | ||||
| 		}, | ||||
| 		serverList:         serverList, | ||||
| 		currentServerIndex: 0, | ||||
| 	}, nil | ||||
| } | ||||
| @ -39,7 +40,6 @@ func NewPoll(serverList []*define.ServerNode) (*Poll, error) { | ||||
| // Date : 12:41 下午 2021/10/19 | ||||
| type Poll struct { | ||||
| 	base | ||||
| 	serverList         []*define.ServerNode | ||||
| 	currentServerIndex int | ||||
| } | ||||
|  | ||||
| @ -48,21 +48,18 @@ type Poll struct { | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:43 下午 2021/10/19 | ||||
| func (p *Poll) GetServerNode() (*define.ServerNode, error) { | ||||
| 	if len(p.serverList) == 0 { | ||||
| 		return nil, errors.New("server list is empty") | ||||
| 	} | ||||
| 	p.Lock() | ||||
| 	defer p.Unlock() | ||||
| func (p *Poll) GetServerNode(req *http.Request) (*define.ServerNode, error) { | ||||
| 	p.RLock() | ||||
| 	defer p.RUnlock() | ||||
| 	var ( | ||||
| 		serverNode *define.ServerNode | ||||
| 	) | ||||
| 	// 循环次数 | ||||
| 	loopTimes := 0 | ||||
| 	for loopTimes < len(p.serverList) { | ||||
| 	for loopTimes < len(p.severList) { | ||||
| 		loopTimes++ | ||||
| 		p.currentServerIndex = (p.currentServerIndex + 1) % len(p.serverList) | ||||
| 		if serverNode = p.serverList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal { | ||||
| 		p.currentServerIndex = (p.currentServerIndex + 1) % len(p.severList) | ||||
| 		if serverNode = p.severList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal { | ||||
| 			continue | ||||
| 		} | ||||
| 		break | ||||
| @ -74,57 +71,3 @@ func (p *Poll) GetServerNode() (*define.ServerNode, error) { | ||||
|  | ||||
| 	return serverNode, nil | ||||
| } | ||||
|  | ||||
| // AddServerNode 新添加一个服务器节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:07 下午 2021/10/20 | ||||
| func (p *Poll) AddServerNode(hostIP string, port int) error { | ||||
| 	if len(hostIP) == 0 || port <= 0 { | ||||
| 		return errors.New("host ip or port is invalid") | ||||
| 	} | ||||
| 	p.Lock() | ||||
| 	defer p.Unlock() | ||||
| 	for _, item := range p.serverList { | ||||
| 		if item.HostIP == hostIP && item.Port == port { | ||||
| 			return errors.New("host config is already exist") | ||||
| 		} | ||||
| 	} | ||||
| 	p.serverList = append(p.serverList, &define.ServerNode{ | ||||
| 		HostIP: hostIP, | ||||
| 		Port:   port, | ||||
| 		Status: define.ServerNodeStatusNormal, | ||||
| 	}) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:19 下午 2021/10/20 | ||||
| func (p *Poll) Remove(hostIP string, port int, force bool) { | ||||
| 	p.Lock() | ||||
| 	defer p.Unlock() | ||||
| 	tmpServerNode := make([]*define.ServerNode, 0) | ||||
| 	for _, item := range p.serverList { | ||||
| 		if item.HostIP == hostIP && item.Port == port { | ||||
| 			if force { | ||||
| 				continue | ||||
| 			} | ||||
| 			item.Status = define.ServerNodeStatusRemove | ||||
| 		} | ||||
| 		tmpServerNode = append(tmpServerNode, item) | ||||
| 	} | ||||
| 	p.serverList = tmpServerNode | ||||
| } | ||||
|  | ||||
| // GetServerNodeList 获取服务器节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:33 下午 2021/10/20 | ||||
| func (p *Poll) GetServerNodeList() []*define.ServerNode { | ||||
| 	return p.serverList | ||||
| } | ||||
|  | ||||
							
								
								
									
										59
									
								
								balance/random.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								balance/random.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // Package balance... | ||||
| // | ||||
| // Description : balance... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-22 6:27 下午 | ||||
| package balance | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/util" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| ) | ||||
|  | ||||
| // NewRandom ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:29 下午 2021/11/22 | ||||
| func NewRandom(severList []*define.ServerNode) (IBalance, error) { | ||||
| 	if nil == severList || len(severList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	return &Random{ | ||||
| 		base{ | ||||
| 			lock:      &sync.RWMutex{}, | ||||
| 			severList: make([]*define.ServerNode, 0), | ||||
| 		}, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Random 随机负载均衡 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:27 下午 2021/11/22 | ||||
| type Random struct { | ||||
| 	base | ||||
| } | ||||
|  | ||||
| // GetServerNode ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:31 下午 2021/11/22 | ||||
| func (r *Random) GetServerNode(req *http.Request) (*define.ServerNode, error) { | ||||
| 	r.RLock() | ||||
| 	defer r.RUnlock() | ||||
| 	if len(r.severList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	randomID := util.GetHashID(util.GenRandomString("", 128)) % uint64(len(r.severList)) | ||||
| 	return r.severList[int(randomID)], nil | ||||
| } | ||||
							
								
								
									
										114
									
								
								balance/weight_serverRound_robin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								balance/weight_serverRound_robin.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,114 @@ | ||||
| // Package balance... | ||||
| // | ||||
| // Description : balance... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-22 6:58 下午 | ||||
| package balance | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/balance/define" | ||||
| ) | ||||
|  | ||||
| // NewWeightServerRoundRobin ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:58 下午 2021/11/22 | ||||
| func NewWeightServerRoundRobin(severList []*define.ServerNode) (IBalance, error) { | ||||
| 	if nil == severList || len(severList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	return &WeightServerRoundRobin{ | ||||
| 		base: base{ | ||||
| 			lock:      &sync.RWMutex{}, | ||||
| 			severList: severList, | ||||
| 		}, | ||||
| 		effectiveWeight: 0, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // WeightServerRoundRobin 加权轮询 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:58 下午 2021/11/22 | ||||
| type WeightServerRoundRobin struct { | ||||
| 	base | ||||
| 	effectiveWeight float64 | ||||
| } | ||||
|  | ||||
| // GetServerNode ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 7:00 下午 2021/11/22 | ||||
| func (w *WeightServerRoundRobin) GetServerNode(req *http.Request) (*define.ServerNode, error) { | ||||
| 	w.RLock() | ||||
| 	defer w.RUnlock() | ||||
| 	if len(w.severList) == 0 { | ||||
| 		return nil, errors.New("sever list is empty") | ||||
| 	} | ||||
| 	var expectBackendServer *define.ServerNode | ||||
| 	for _, backendServer := range w.severList { | ||||
| 		// 给每个后端服务增加自身权重 | ||||
| 		backendServer.CurrentWeight += backendServer.Weight | ||||
| 		if expectBackendServer == nil { | ||||
| 			expectBackendServer = backendServer | ||||
| 		} | ||||
| 		if backendServer.CurrentWeight > expectBackendServer.CurrentWeight { | ||||
| 			expectBackendServer = backendServer | ||||
| 		} | ||||
| 	} | ||||
| 	// 把选择的后端服务权重减掉总权重 | ||||
| 	expectBackendServer.CurrentWeight -= w.effectiveWeight | ||||
| 	return expectBackendServer, nil | ||||
| } | ||||
|  | ||||
| // AddServerNode 新添加一个服务器节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:07 下午 2021/10/20 | ||||
| func (w *WeightServerRoundRobin) AddServerNode(node *define.ServerNode) error { | ||||
| 	if len(node.HostIP) == 0 || node.Port <= 0 { | ||||
| 		return errors.New("host ip or port is invalid") | ||||
| 	} | ||||
| 	w.Lock() | ||||
| 	defer w.Unlock() | ||||
| 	for _, item := range w.severList { | ||||
| 		if item.HostIP == node.HostIP && item.Port == node.Port { | ||||
| 			return errors.New("host config is already exist") | ||||
| 		} | ||||
| 	} | ||||
| 	w.effectiveWeight += node.Weight | ||||
| 	w.severList = append(w.severList, node) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:19 下午 2021/10/20 | ||||
| func (w *WeightServerRoundRobin) Remove(hostIP string, port int, force bool) { | ||||
| 	w.Lock() | ||||
| 	defer w.Unlock() | ||||
| 	tmpServerNode := make([]*define.ServerNode, 0) | ||||
| 	for _, item := range w.severList { | ||||
| 		if item.HostIP == hostIP && item.Port == port { | ||||
| 			if force { | ||||
| 				continue | ||||
| 			} | ||||
| 			item.Status = define.ServerNodeStatusRemove | ||||
| 		} | ||||
| 		tmpServerNode = append(tmpServerNode, item) | ||||
| 	} | ||||
| 	w.severList = tmpServerNode | ||||
| } | ||||
							
								
								
									
										42
									
								
								cmd/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								cmd/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| // Package cmd... | ||||
| // | ||||
| // Description : cmd... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-12 2:18 下午 | ||||
| package cmd | ||||
|  | ||||
| // Config 配置 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:19 下午 2021/11/12 | ||||
| type Config struct { | ||||
| 	WorkDir       string      `json:"work_dir"`       // 工作目录 | ||||
| 	Command       string      `json:"command"`        // 指令 | ||||
| 	Script        string      `json:"script"`         // 脚本 | ||||
| 	ParameterList []Parameter `json:"parameter_list"` // 参数列表 | ||||
| } | ||||
|  | ||||
| // Parameter ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:21 下午 2021/11/12 | ||||
| type Parameter struct { | ||||
| 	Key   string `json:"key"` | ||||
| 	Value string `json:"value"` | ||||
| } | ||||
|  | ||||
| // Result ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:25 下午 2021/11/12 | ||||
| type Result struct { | ||||
| 	WorkDir        string `json:"work_dir"` | ||||
| 	Err            error  `json:"err"` | ||||
| 	Output         []byte `json:"output"` | ||||
| 	ExecuteCommand string `json:"execute_command"` | ||||
| } | ||||
							
								
								
									
										58
									
								
								cmd/execute.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								cmd/execute.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| // Package cmd... | ||||
| // | ||||
| // Description : cmd... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-12 2:21 下午 | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"os/exec" | ||||
| 	"strings" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/util" | ||||
| ) | ||||
|  | ||||
| // Execute 执行指令 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:22 下午 2021/11/12 | ||||
| func Execute(cmdConfig Config) *Result { | ||||
| 	if len(cmdConfig.WorkDir) == 0 { | ||||
| 		cmdConfig.WorkDir, _ = util.GetProjectPath() | ||||
| 	} | ||||
| 	paramList := buildCmdParameter(cmdConfig.Script, cmdConfig.ParameterList) | ||||
| 	cmdInstance := exec.Command(cmdConfig.Command, paramList...) | ||||
| 	// 设置指令的工作目录 | ||||
| 	cmdInstance.Dir = cmdConfig.WorkDir | ||||
| 	result := &Result{ | ||||
| 		Err:            nil, | ||||
| 		Output:         nil, | ||||
| 		WorkDir:        cmdConfig.WorkDir, | ||||
| 		ExecuteCommand: cmdConfig.Command + " " + strings.Join(paramList, " "), | ||||
| 	} | ||||
| 	result.Output, result.Err = cmdInstance.CombinedOutput() | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // buildCmdParameter 构建参数列表 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:53 下午 2021/11/12 | ||||
| func buildCmdParameter(script string, parameterList []Parameter) []string { | ||||
| 	paramList := make([]string, 0) | ||||
| 	if len(script) > 0 { | ||||
| 		paramList = append(paramList, script) | ||||
| 	} | ||||
| 	for _, item := range parameterList { | ||||
| 		if len(item.Key) == 0 { | ||||
| 			paramList = append(paramList, item.Value) | ||||
| 			continue | ||||
| 		} | ||||
| 		paramList = append(paramList, item.Key+"="+item.Value) | ||||
| 	} | ||||
| 	return paramList | ||||
| } | ||||
							
								
								
									
										103
									
								
								consistent_hash/consistent.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								consistent_hash/consistent.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| // Package consistent_hash... | ||||
| // | ||||
| // Description : consistent_hash... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-21 4:57 下午 | ||||
| package consistent_hash | ||||
|  | ||||
| import ( | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // New 获取实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:03 下午 2021/11/21 | ||||
| func New(replicas int, fn HashFunc) *Consistent { | ||||
| 	if nil == fn { | ||||
| 		fn = DefaultHashFunc | ||||
| 	} | ||||
| 	return &Consistent{ | ||||
| 		hashFunc: fn, | ||||
| 		replicas: replicas, | ||||
| 		keys:     make([]int, 0), | ||||
| 		hashMap:  make(map[int]string), | ||||
| 		lock:     &sync.RWMutex{}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Consistent ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:00 下午 2021/11/21 | ||||
| type Consistent struct { | ||||
| 	hashFunc HashFunc       // 哈希函数 | ||||
| 	replicas int            // 虚拟的数量 | ||||
| 	keys     []int          // 哈希环 | ||||
| 	hashMap  map[int]string // 虚拟节点与真实节点的映射表 | ||||
| 	lock     *sync.RWMutex  // 锁 | ||||
| } | ||||
|  | ||||
| // Add 添加节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:10 下午 2021/11/21 | ||||
| func (c *Consistent) Add(keyList ...string) { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
| 	for _, key := range keyList { | ||||
| 		for i := 0; i < c.replicas; i++ { | ||||
| 			hash := int(c.hashFunc([]byte(strconv.Itoa(i) + key))) | ||||
| 			c.keys = append(c.keys, hash) | ||||
| 			c.hashMap[hash] = key | ||||
| 		} | ||||
| 	} | ||||
| 	// 哈希值排序 | ||||
| 	sort.Ints(c.keys) | ||||
| } | ||||
|  | ||||
| // Get 获取节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:16 下午 2021/11/21 | ||||
| func (c *Consistent) Get(key string) string { | ||||
| 	c.lock.RLock() | ||||
| 	defer c.lock.Unlock() | ||||
| 	if len(c.keys) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	hash := int(c.hashFunc([]byte(key))) | ||||
| 	// 查找节点索引 | ||||
| 	idx := sort.Search(len(c.keys), func(i int) bool { | ||||
| 		return c.keys[i] >= hash | ||||
| 	}) | ||||
| 	return c.hashMap[c.keys[idx%len(c.keys)]] | ||||
| } | ||||
|  | ||||
| // Delete 删除一个节点,本质逻辑 : 重建哈希环 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:35 下午 2021/11/21 | ||||
| func (c *Consistent) Delete(key string) { | ||||
| 	c.lock.Lock() | ||||
| 	defer c.lock.Unlock() | ||||
| 	tmpKeyList := make([]string, 0) | ||||
| 	for _, k := range c.hashMap { | ||||
| 		if k == key { | ||||
| 			continue | ||||
| 		} | ||||
| 		tmpKeyList = append(tmpKeyList, k) | ||||
| 	} | ||||
| 	c.hashMap = make(map[int]string) | ||||
| 	c.keys = make([]int, 0) | ||||
| 	c.Add(tmpKeyList...) | ||||
| } | ||||
							
								
								
									
										22
									
								
								consistent_hash/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								consistent_hash/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| // Package consistent_hash... | ||||
| // | ||||
| // Description : consistent_hash... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-21 4:49 下午 | ||||
| package consistent_hash | ||||
|  | ||||
| import "hash/crc32" | ||||
|  | ||||
| // HashFunc 哈希函数定义 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:50 下午 2021/11/21 | ||||
| type HashFunc func(data []byte) uint32 | ||||
|  | ||||
| var ( | ||||
| 	// DefaultHashFunc 默认的哈希函数 | ||||
| 	DefaultHashFunc = crc32.ChecksumIEEE | ||||
| ) | ||||
							
								
								
									
										82
									
								
								excel/create.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								excel/create.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| // Package excel... | ||||
| // | ||||
| // Description : excel... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-19 12:25 下午 | ||||
| package excel | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/xuri/excelize/v2" | ||||
| ) | ||||
|  | ||||
| // NewExcel 获取excel实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:28 下午 2021/11/19 | ||||
| func NewExcel() *Create { | ||||
| 	return &Create{ | ||||
| 		fileHandler: excelize.NewFile(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Create 创建excel | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:27 下午 2021/11/19 | ||||
| type Create struct { | ||||
| 	// fileHandler excel文件处理句柄 | ||||
| 	fileHandler *excelize.File | ||||
| } | ||||
|  | ||||
| // GenerateSheet 生成sheet | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:43 下午 2021/11/19 | ||||
| func (c *Create) GenerateSheet(sheetList []SheetData) error { | ||||
| 	for _, sheet := range sheetList { | ||||
| 		sheetIndex := c.fileHandler.NewSheet(sheet.Name) | ||||
| 		if sheet.IsDefault { | ||||
| 			// 设置活跃 | ||||
| 			c.fileHandler.SetActiveSheet(sheetIndex) | ||||
| 		} | ||||
| 		for lineIdx, colList := range sheet.Data { | ||||
| 			for colIdx, col := range colList { | ||||
| 				position := c.getColPosition(colIdx, lineIdx) | ||||
| 				if err := c.fileHandler.SetCellValue(sheet.Name, position, col); nil != err { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Save 保存文件 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:04 下午 2021/11/19 | ||||
| func (c *Create) Save(fullFilePath string) error { | ||||
| 	return c.fileHandler.SaveAs(fullFilePath) | ||||
| } | ||||
|  | ||||
| // getColPosition 获取列名 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 3:14 下午 2021/11/19 | ||||
| func (c *Create) getColPosition(colIndex int, dataLineIndex int) string { | ||||
| 	realIndex := colIndex % 26 | ||||
| 	first := colIndex / 26 | ||||
| 	if first == 0 { | ||||
| 		return fmt.Sprintf("%s%d", WordMap[realIndex], dataLineIndex+1) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s%s%d", WordMap[first], WordMap[realIndex], dataLineIndex+1) | ||||
| } | ||||
							
								
								
									
										61
									
								
								excel/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								excel/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| // Package excel... | ||||
| // | ||||
| // Description : excel... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-19 11:57 上午 | ||||
| package excel | ||||
|  | ||||
| // ReadResult ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:57 上午 2021/11/19 | ||||
| type ReadResult struct { | ||||
| 	Error  error                               // 异常信息 | ||||
| 	Result map[string][]map[string]interface{} // 查询结果 sheet => dataList | ||||
| } | ||||
|  | ||||
| // SheetData ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:35 下午 2021/11/19 | ||||
| type SheetData struct { | ||||
| 	IsDefault bool            // 是否默认工作表 | ||||
| 	Name      string          // sheet 名称 | ||||
| 	Data      [][]interface{} // 数据列表 | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	// WordMap 单元格序号映射 | ||||
| 	WordMap = map[int]string{ | ||||
| 		0:  "A", | ||||
| 		1:  "B", | ||||
| 		2:  "C", | ||||
| 		3:  "D", | ||||
| 		4:  "E", | ||||
| 		5:  "F", | ||||
| 		6:  "G", | ||||
| 		7:  "H", | ||||
| 		8:  "I", | ||||
| 		9:  "J", | ||||
| 		10: "K", | ||||
| 		11: "L", | ||||
| 		12: "M", | ||||
| 		13: "N", | ||||
| 		14: "O", | ||||
| 		15: "P", | ||||
| 		16: "Q", | ||||
| 		17: "R", | ||||
| 		18: "S", | ||||
| 		19: "T", | ||||
| 		20: "U", | ||||
| 		21: "V", | ||||
| 		22: "W", | ||||
| 		23: "X", | ||||
| 		24: "Y", | ||||
| 		25: "Z", | ||||
| 	} | ||||
| ) | ||||
							
								
								
									
										174
									
								
								excel/read.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								excel/read.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | ||||
| // Package excel... | ||||
| // | ||||
| // Description : excel... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-19 3:59 下午 | ||||
| package excel | ||||
|  | ||||
| import ( | ||||
| 	"github.com/xuri/excelize/v2" | ||||
| ) | ||||
|  | ||||
| // NewRead 获取读取实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:00 下午 2021/11/19 | ||||
| func NewRead(fullFilePath string, filePassword string) (*Read, error) { | ||||
| 	var err error | ||||
| 	read := &Read{} | ||||
| 	if read.fileHandler, err = excelize.OpenFile(fullFilePath, excelize.Options{Password: filePassword}); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return read, nil | ||||
| } | ||||
|  | ||||
| // Read ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:03 下午 2021/11/19 | ||||
| type Read struct { | ||||
| 	fileHandler *excelize.File | ||||
| } | ||||
|  | ||||
| // GetAllSheetList ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:06 下午 2021/11/19 | ||||
| func (r *Read) GetAllSheetList() []string { | ||||
| 	return r.fileHandler.GetSheetList() | ||||
| } | ||||
|  | ||||
| // GetAllData 读取全部数据 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:07 下午 2021/11/19 | ||||
| func (r *Read) GetAllData() (map[string][][]string, error) { | ||||
| 	var ( | ||||
| 		sheetList []string | ||||
| 		result    map[string][][]string | ||||
| 		err       error | ||||
| 	) | ||||
| 	sheetList = r.GetAllSheetList() | ||||
| 	result = make(map[string][][]string) | ||||
| 	for _, sheetName := range sheetList { | ||||
| 		if result[sheetName], err = r.fileHandler.GetRows(sheetName); nil != err { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // GetAllDataToMap 读取全部数据,并返回map结构 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:20 下午 2021/11/19 | ||||
| func (r *Read) GetAllDataToMap(fieldList []string) (map[string][]map[string]string, error) { | ||||
| 	var ( | ||||
| 		allData      map[string][][]string | ||||
| 		err          error | ||||
| 		formatResult map[string][]map[string]string | ||||
| 	) | ||||
| 	formatResult = make(map[string][]map[string]string) | ||||
| 	if allData, err = r.GetAllData(); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for sheetName, sheetData := range allData { | ||||
| 		formatResult[sheetName] = make([]map[string]string, 0) | ||||
| 		for _, lineData := range sheetData { | ||||
| 			tmpResult := make(map[string]string) | ||||
| 			for idx, colData := range lineData { | ||||
| 				if idx >= len(fieldList) { | ||||
| 					// 指定的字段列表较短, 自动剔除后面的字段 | ||||
| 					break | ||||
| 				} | ||||
| 				tmpResult[fieldList[idx]] = colData | ||||
| 			} | ||||
| 			// 字段列表较长, 单元格不足, 自动补齐空字符串 | ||||
| 			for i := len(lineData); i < len(fieldList); i++ { | ||||
| 				tmpResult[fieldList[i]] = "" | ||||
| 			} | ||||
| 			formatResult[sheetName] = append(formatResult[sheetName], tmpResult) | ||||
| 		} | ||||
| 	} | ||||
| 	// 格式化数据 | ||||
| 	return formatResult, nil | ||||
| } | ||||
|  | ||||
| // ExtractAssignCol 抽取指定的列,并返回list数据, 列的计数从 0 开始 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:53 下午 2021/11/19 | ||||
| func (r *Read) ExtractAssignCol(colIndexList []int) (map[string][][]string, error) { | ||||
| 	var ( | ||||
| 		allData      map[string][][]string | ||||
| 		err          error | ||||
| 		formatResult map[string][][]string | ||||
| 	) | ||||
| 	if allData, err = r.GetAllData(); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	formatResult = make(map[string][][]string) | ||||
| 	for sheetName, sheetData := range allData { | ||||
| 		formatResult[sheetName] = make([][]string, 0) | ||||
| 		for _, lineData := range sheetData { | ||||
| 			tmpData := make([]string, 0) | ||||
| 			for _, colIdx := range colIndexList { | ||||
| 				if len(lineData) <= colIdx { | ||||
| 					// 索引越界,默认空值 | ||||
| 					tmpData = append(tmpData, "") | ||||
| 					continue | ||||
| 				} | ||||
| 				tmpData = append(tmpData, lineData[colIdx]) | ||||
| 			} | ||||
| 			formatResult[sheetName] = append(formatResult[sheetName], tmpData) | ||||
| 		} | ||||
| 	} | ||||
| 	return formatResult, nil | ||||
| } | ||||
|  | ||||
| // ExtractAssignColToMap 抽取指定的列,并返回map数据 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:53 下午 2021/11/19 | ||||
| func (r *Read) ExtractAssignColToMap(ruleTable map[int]string) (map[string][]map[string]string, error) { | ||||
| 	var ( | ||||
| 		allData      map[string][][]string | ||||
| 		err          error | ||||
| 		formatResult map[string][]map[string]string | ||||
| 	) | ||||
| 	formatResult = make(map[string][]map[string]string) | ||||
| 	if allData, err = r.GetAllData(); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for sheetName, sheetData := range allData { | ||||
| 		formatResult[sheetName] = make([]map[string]string, 0) | ||||
| 		for _, lineData := range sheetData { | ||||
| 			tmpResult := make(map[string]string) | ||||
| 			for idx, colData := range lineData { | ||||
| 				colName, exist := ruleTable[idx] | ||||
| 				if !exist { | ||||
| 					// 当前字段不需要提取 | ||||
| 					continue | ||||
| 				} | ||||
| 				tmpResult[colName] = colData | ||||
| 			} | ||||
| 			for _, colName := range ruleTable { | ||||
| 				if _, exist := tmpResult[colName]; !exist { | ||||
| 					tmpResult[colName] = "" | ||||
| 				} | ||||
| 			} | ||||
| 			formatResult[sheetName] = append(formatResult[sheetName], tmpResult) | ||||
| 		} | ||||
| 	} | ||||
| 	// 格式化数据 | ||||
| 	return formatResult, nil | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| // Package gin ... | ||||
| // Package api ... | ||||
| // | ||||
| // Description : 便捷的相关API处理 | ||||
| // | ||||
| @ -23,7 +23,7 @@ type IApi interface { | ||||
| 	GetURI() string | ||||
| 	// GetMiddleWareList 使用的中间件列表 | ||||
| 	GetMiddleWareList() []gin.HandlerFunc | ||||
| 	// 处理的handler | ||||
| 	// GetHandler 处理的handler | ||||
| 	GetHandler() gin.HandlerFunc | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										17
									
								
								git_hook/abstract.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								git_hook/abstract.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| // Package git_hook... | ||||
| // | ||||
| // Description : git_hook... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-11 6:41 下午 | ||||
| package git_hook | ||||
|  | ||||
| import "github.com/gin-gonic/gin" | ||||
|  | ||||
| // IGitHookEventHandler 接口约束, pkg 内部会提供基础实现 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:42 下午 2021/11/11 | ||||
| type IGitHookEventHandler func(ctx *gin.Context, hookData *HookData) *ResponseData | ||||
							
								
								
									
										165
									
								
								git_hook/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								git_hook/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | ||||
| // Package git_hook... | ||||
| // | ||||
| // Description : git_hook... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-11 6:23 下午 | ||||
| package git_hook | ||||
|  | ||||
| // HookData hook通知数据 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:23 下午 2021/11/11 | ||||
| type HookData struct { | ||||
| 	Repository Repository `json:"repository"` // 仓库信息 | ||||
| 	Sender     User       `json:"sender"` | ||||
| 	Ref        string     `json:"ref"`         // 分支,如 : refs/heads/master | ||||
| 	Before     string     `json:"before"`      // 之前版本号 : e162757f3f4a37786b4118a5346baae5dd24ecde | ||||
| 	After      string     `json:"after"`       // 当前版本号 : c70a362d850a820704bd374363ea4e7ea810fd1a | ||||
| 	HeadCommit Commit     `json:"head_commit"` // 最近一次提交 | ||||
| 	CompareUrl string     `json:"compare_url"` // 两个版本号代码diff的URL, 点击后可查看diff | ||||
| 	Commits    []Commit   `json:"commits"`     // 提交记录列表 | ||||
| 	Pusher     User       `json:"pusher"`      // 推送人信息 | ||||
| } | ||||
|  | ||||
| // Repository 仓库信息 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:24 下午 2021/11/11 | ||||
| type Repository struct { | ||||
| 	Mirror                    bool                      `json:"mirror"` | ||||
| 	OriginalUrl               string                    `json:"original_url"`                // original_url | ||||
| 	StarsCount                int64                     `json:"stars_count"`                 // start 数量 | ||||
| 	IgnoreWhitespaceConflicts bool                      `json:"ignore_whitespace_conflicts"` // 忽略空格的冲突 | ||||
| 	FullName                  string                    `json:"full_name"`                   // 仓库完整名称 | ||||
| 	Fork                      bool                      `json:"fork"`                        // 是否 fork | ||||
| 	CreatedAt                 string                    `json:"created_at"`                  // 创建时间 | ||||
| 	Internal                  bool                      `json:"internal"`                    // 是否内部仓库 | ||||
| 	AllowRebaseExplicit       bool                      `json:"allow_rebase_explicit"`       // 是否允许rebase | ||||
| 	MirrorInterval            string                    `json:"mirror_interval"`             // mirror_interval | ||||
| 	CloneUrl                  string                    `json:"clone_url"`                   // gi clone 对用的 https 地址 | ||||
| 	WatchersCount             int64                     `json:"watchers_count"`              // 监听器数量 | ||||
| 	OpenIssuesCount           int64                     `json:"open_issues_count"`           // 未解决的issues数量 | ||||
| 	ReleaseCounter            int64                     `json:"release_counter"`             // 发布版本数量 | ||||
| 	InternalTracker           RepositoryInternalTracker `json:"internal_tracker"`            // 内部跟踪配置 | ||||
| 	Name                      string                    `json:"name"`                        // 仓库名称 | ||||
| 	Empty                     bool                      `json:"empty"`                       // 仓库是否为空 | ||||
| 	SshUrl                    string                    `json:"ssh_url"`                     // git clone 对应的  ssh 地址 | ||||
| 	ForksCount                int64                     `json:"forks_count"`                 // fork 次数 | ||||
| 	Permissions               RepositoryPermission      `json:"permissions"`                 // 权限配置 | ||||
| 	Private                   bool                      `json:"private"`                     // 是否为私有仓库 | ||||
| 	Size                      int64                     `json:"size"`                        // 仓库大小 KB | ||||
| 	HasWiki                   bool                      `json:"has_wiki"`                    // 是否有 wiki | ||||
| 	HasProjects               bool                      `json:"has_projects"`                // 是否有项目 | ||||
| 	AllowMergeCommits         bool                      `json:"allow_merge_commits"`         // 是否允许合并提交 | ||||
| 	AvatarUrl                 string                    `json:"avatar_url"`                  // 头像地址 | ||||
| 	ID                        int64                     `json:"id"`                          // 仓库ID | ||||
| 	Description               string                    `json:"description"`                 // 创建仓库时候的描述 | ||||
| 	Website                   string                    `json:"website"`                     // 网站 | ||||
| 	UpdatedAt                 string                    `json:"updated_at"`                  // 更新时间 | ||||
| 	HasPullRequests           bool                      `json:"has_pull_requests"`           // 是否有 pull request | ||||
| 	Parent                    map[string]interface{}    `json:"parent"`                      // parent | ||||
| 	OpenPrCounter             int64                     `json:"open_pr_counter"`             // 打开的pr数量 | ||||
| 	HasIssues                 bool                      `json:"has_issues"`                  // 是否有issues | ||||
| 	AllowRebase               bool                      `json:"allow_rebase"`                // 是否允许rebase | ||||
| 	AllowSquashMerge          bool                      `json:"allow_squash_merge"`          // 是否允许 合并 merge (将分支内容合并成一次提交, 合入主干) | ||||
| 	Owner                     User                      `json:"owner"`                       // 仓库所有者信息 | ||||
| 	Template                  bool                      `json:"template"`                    // 是否是模版 | ||||
| 	HtmlUrl                   string                    `json:"html_url"`                    // 访问仓库的html地址 | ||||
| 	DefaultBranch             string                    `json:"default_branch"`              // 默认分支 | ||||
| 	Archived                  bool                      `json:"archived"`                    // 是否已归档 | ||||
| 	DefaultMergeStyle         string                    `json:"default_merge_style"`         // 默认的合并方式 | ||||
| } | ||||
|  | ||||
| // RepositoryInternalTracker 内部跟踪器 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:28 下午 2021/11/11 | ||||
| type RepositoryInternalTracker struct { | ||||
| 	EnableTimeTracker                bool `json:"enable_time_tracker"`                   // 启用time_tracker | ||||
| 	AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` // 仅有代码贡献者允许 | ||||
| 	EnableIssueDependencies          bool `json:"enable_issue_dependencies"`             // 启用 issue_dependencies | ||||
| } | ||||
|  | ||||
| // RepositoryPermission 仓库权限 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:29 下午 2021/11/11 | ||||
| type RepositoryPermission struct { | ||||
| 	Pull  bool `json:"pull"`  // 是否允许 pull 代码 | ||||
| 	Admin bool `json:"admin"` // 是否是管理员 | ||||
| 	Push  bool `json:"push"`  // 是否允许push代码 | ||||
| } | ||||
|  | ||||
| // User 用户信息 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:30 下午 2021/11/11 | ||||
| type User struct { | ||||
| 	IsAdmin           bool   `json:"is_admin"`            // 是否是管理员 | ||||
| 	Website           string `json:"website"`             // 网页 | ||||
| 	Email             string `json:"email"`               // 邮箱 | ||||
| 	AvatarUrl         string `json:"avatar_url"`          // 头像 | ||||
| 	ProhibitLogin     bool   `json:"prohibit_login"`      // 禁止登录 | ||||
| 	Description       string `json:"description"`         // 描述 | ||||
| 	FollowingCount    int64  `json:"following_count"`     // follower数量 | ||||
| 	StarredReposCount int64  `json:"starred_repos_count"` // star仓库数量 | ||||
| 	Username          string `json:"username"`            // 用户名 | ||||
| 	Login             string `json:"login"`               // 登录 | ||||
| 	Created           string `json:"created"`             // 创建时间 | ||||
| 	Visibility        string `json:"visibility"`          // 是否可见 | ||||
| 	FullName          string `json:"full_name"`           // 全名 | ||||
| 	LastLogin         string `json:"last_login"`          // 最近登录时间 | ||||
| 	Restricted        bool   `json:"restricted"`          // 是否受限 | ||||
| 	Active            bool   `json:"active"`              // 是否活跃 | ||||
| 	Location          string `json:"location"`            // 位置 | ||||
| 	FollowersCount    int64  `json:"followers_count"`     // follower数量 | ||||
| 	ID                int64  `json:"id"`                  // id | ||||
| 	Language          string `json:"language"`            // 语言 | ||||
| } | ||||
|  | ||||
| // Commit 提交记录信息 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:25 下午 2021/11/11 | ||||
| type Commit struct { | ||||
| 	Message      string                 `json:"message"`      // 提交时带的message | ||||
| 	Url          string                 `json:"url"`          // 浏览此版本代码的地址 | ||||
| 	Author       CommitAuthor           `json:"author"`       // 作者信息 | ||||
| 	Verification map[string]interface{} `json:"verification"` // 验证 | ||||
| 	Timestamp    string                 `json:"timestamp"`    // 时间 | ||||
| 	ID           string                 `json:"id"`           // 提交的版本号 98ccd35d19d17c8e624a492cc5811fe6f381ca09 | ||||
| 	Committer    CommitAuthor           `json:"committer"`    // 提交人信息 | ||||
| 	Added        []string               `json:"added"`        // 增加的文件列表 | ||||
| 	Removed      []string               `json:"removed"`      // 移除文件列表 | ||||
| 	Modified     []string               `json:"modified"`     // 修改的文件列表 | ||||
| } | ||||
|  | ||||
| // CommitAuthor 提交人的信息 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:31 下午 2021/11/11 | ||||
| type CommitAuthor struct { | ||||
| 	Name     string `json:"name"`     // 昵称 | ||||
| 	Email    string `json:"email"`    // 邮箱 | ||||
| 	Username string `json:"username"` // 用户名 | ||||
| } | ||||
|  | ||||
| // ResponseData 处理结果的返回值 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:37 上午 2021/11/12 | ||||
| type ResponseData struct { | ||||
| 	Code    interface{} `json:"code"` | ||||
| 	Message string      `json:"message"` | ||||
| 	Data    interface{} `json:"data"` | ||||
| } | ||||
							
								
								
									
										45
									
								
								git_hook/register.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								git_hook/register.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| // Package git_hook... | ||||
| // | ||||
| // Description : git_hook... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-11 6:39 下午 | ||||
| package git_hook | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| // RegisterGitHookRouter 注册 git hook 回调的路由 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:40 下午 2021/11/11 | ||||
| func RegisterGitHookRouter(router *gin.Engine, handler IGitHookEventHandler) error { | ||||
| 	if nil == handler { | ||||
| 		return errors.New("handler is nil") | ||||
| 	} | ||||
| 	router.POST("/git/hook/notice", func(ctx *gin.Context) { | ||||
| 		var ( | ||||
| 			hookData HookData | ||||
| 			err      error | ||||
| 		) | ||||
| 		if err = ctx.ShouldBindJSON(&hookData); nil != err { | ||||
| 			ctx.JSON(http.StatusBadRequest, gin.H{"code": -1, "message": err.Error()}) | ||||
| 		} | ||||
| 		responseData := handler(ctx, &hookData) | ||||
| 		if nil == responseData { | ||||
| 			responseData = &ResponseData{ | ||||
| 				Code:    100, | ||||
| 				Message: "处理完成(未设置返回值,系统默认返回此信息)", | ||||
| 				Data:    map[string]interface{}{}, | ||||
| 			} | ||||
| 		} | ||||
| 		ctx.JSON(http.StatusOK, responseData) | ||||
| 	}) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										12
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								go.mod
									
									
									
									
									
								
							| @ -14,6 +14,7 @@ require ( | ||||
| 	github.com/spaolacci/murmur3 v1.1.0 | ||||
| 	github.com/stretchr/testify v1.7.0 | ||||
| 	github.com/tidwall/gjson v1.9.0 | ||||
| 	github.com/xuri/excelize/v2 v2.4.1 | ||||
| 	github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 | ||||
| 	go.uber.org/zap v1.19.1 | ||||
| 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | ||||
| @ -54,19 +55,24 @@ require ( | ||||
| 	github.com/mattn/go-isatty v0.0.12 // indirect | ||||
| 	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect | ||||
| 	github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect | ||||
| 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect | ||||
| 	github.com/pierrec/lz4 v2.6.0+incompatible // indirect | ||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||
| 	github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect | ||||
| 	github.com/richardlehane/mscfb v1.0.3 // indirect | ||||
| 	github.com/richardlehane/msoleps v1.0.1 // indirect | ||||
| 	github.com/tidwall/match v1.0.3 // indirect | ||||
| 	github.com/tidwall/pretty v1.1.0 // indirect | ||||
| 	github.com/tklauser/go-sysconf v0.3.9 // indirect | ||||
| 	github.com/tklauser/numcpus v0.3.0 // indirect | ||||
| 	github.com/ugorji/go/codec v1.1.7 // indirect | ||||
| 	github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect | ||||
| 	go.uber.org/atomic v1.7.0 // indirect | ||||
| 	go.uber.org/multierr v1.6.0 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect | ||||
| 	golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect | ||||
| 	golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect | ||||
| 	golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect | ||||
| 	golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect | ||||
| 	golang.org/x/text v0.3.7 // indirect | ||||
| 	google.golang.org/protobuf v1.26.0 // indirect | ||||
| 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect | ||||
|  | ||||
							
								
								
									
										27
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								go.sum
									
									
									
									
									
								
							| @ -121,6 +121,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||
| github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= | ||||
| github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= | ||||
| github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
| github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | ||||
| github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | ||||
| @ -143,6 +145,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= | ||||
| github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= | ||||
| github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI= | ||||
| github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= | ||||
| github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= | ||||
| github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= | ||||
| github.com/shirou/gopsutil v3.21.9+incompatible h1:LTLpUnfX81MkHeCtSrwNKZwuW5Id6kCa7/P43NdcNn4= | ||||
| github.com/shirou/gopsutil v3.21.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= | ||||
| github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= | ||||
| @ -170,6 +176,10 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs | ||||
| github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= | ||||
| github.com/xdg/scram v1.0.3/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= | ||||
| github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= | ||||
| github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o= | ||||
| github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= | ||||
| github.com/xuri/excelize/v2 v2.4.1 h1:veeeFLAJwsNEBPBlDepzPIYS1eLyBVcXNZUW79exZ1E= | ||||
| github.com/xuri/excelize/v2 v2.4.1/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A= | ||||
| github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ= | ||||
| github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= | ||||
| github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| @ -187,8 +197,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk | ||||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= | ||||
| golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI= | ||||
| golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= | ||||
| golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= | ||||
| golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| @ -203,8 +217,11 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||||
| golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= | ||||
| golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= | ||||
| golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0= | ||||
| golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| @ -226,14 +243,16 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w | ||||
| golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s= | ||||
| golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= | ||||
| golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | ||||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
|  | ||||
							
								
								
									
										139
									
								
								middleware/mysql/wrapper/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								middleware/mysql/wrapper/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,139 @@ | ||||
| // Package wrapper... | ||||
| // | ||||
| // Description : wrapper... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-15 6:02 下午 | ||||
| package wrapper | ||||
|  | ||||
| import ( | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/middleware/mysql" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
|  | ||||
| // DBConfig ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 7:00 下午 2021/11/15 | ||||
| type DBConfig struct { | ||||
| 	DBConfig  *mysql.DBConfig | ||||
| 	LogConfig *mysql.LogConfig | ||||
| } | ||||
|  | ||||
| // DBWrapperConfig ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:58 下午 2021/11/15 | ||||
| type DBWrapperConfig struct { | ||||
| 	Write *DBConfig | ||||
| 	Read  *DBConfig | ||||
| } | ||||
|  | ||||
| // NewDBWrapper 获取包装后的数据库实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:45 下午 2021/11/15 | ||||
| func NewDBWrapper(cf *DBWrapperConfig) (*DBWrapper, error) { | ||||
| 	var ( | ||||
| 		err error | ||||
| 	) | ||||
| 	if nil == cf { | ||||
| 		return nil, errors.New("cf is nil") | ||||
| 	} | ||||
|  | ||||
| 	if nil == cf.Write { | ||||
| 		return nil, errors.New("write cf is nil") | ||||
| 	} | ||||
|  | ||||
| 	if nil == cf.Read { | ||||
| 		return nil, errors.New("read cf is nil") | ||||
| 	} | ||||
|  | ||||
| 	wrapperInstance := &DBWrapper{} | ||||
| 	if wrapperInstance.write, err = mysql.GetDatabaseClient(cf.Write.DBConfig, cf.Write.LogConfig); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if wrapperInstance.read, err = mysql.GetDatabaseClient(cf.Read.DBConfig, cf.Read.LogConfig); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return wrapperInstance, nil | ||||
| } | ||||
|  | ||||
| // DBWrapper 数据库包装 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:02 下午 2021/11/15 | ||||
| type DBWrapper struct { | ||||
| 	read  *gorm.DB // 读库实例 | ||||
| 	write *gorm.DB // 写库实例 | ||||
| } | ||||
|  | ||||
| // SelectDBOption 数据库实力选择时的选项 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:33 下午 2021/11/15 | ||||
| type SelectDBOption struct { | ||||
| 	Table       string | ||||
| 	ForceMaster bool | ||||
| } | ||||
|  | ||||
| // SetSelectDBOption 设置选项 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:34 下午 2021/11/15 | ||||
| type SetSelectDBOption func(o *SelectDBOption) | ||||
|  | ||||
| // GetWriteInstance 获取主库实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:31 下午 2021/11/15 | ||||
| func (dw *DBWrapper) GetWriteInstance(instanceOptionList ...SetSelectDBOption) *gorm.DB { | ||||
| 	option := dw.getOption(instanceOptionList...) | ||||
| 	instance := dw.write | ||||
| 	if len(option.Table) > 0 { | ||||
| 		instance.Table(option.Table) | ||||
| 	} | ||||
| 	return instance | ||||
| } | ||||
|  | ||||
| // GetReadInstance 获取读库实例 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:32 下午 2021/11/15 | ||||
| func (dw *DBWrapper) GetReadInstance(instanceOptionList ...SetSelectDBOption) *gorm.DB { | ||||
| 	option := dw.getOption(instanceOptionList...) | ||||
| 	instance := dw.read | ||||
| 	if option.ForceMaster || nil == dw.read { | ||||
| 		instance = dw.write | ||||
| 	} | ||||
| 	if len(option.Table) > 0 { | ||||
| 		instance.Table(option.Table) | ||||
| 	} | ||||
| 	return instance | ||||
| } | ||||
|  | ||||
| // getOption 生成option | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:35 下午 2021/11/15 | ||||
| func (dw *DBWrapper) getOption(instanceOptionList ...SetSelectDBOption) *SelectDBOption { | ||||
| 	o := &SelectDBOption{ | ||||
| 		Table:       "", | ||||
| 		ForceMaster: false, | ||||
| 	} | ||||
| 	for _, f := range instanceOptionList { | ||||
| 		f(o) | ||||
| 	} | ||||
| 	return o | ||||
| } | ||||
							
								
								
									
										8
									
								
								middleware/tile38/define.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								middleware/tile38/define.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| // Package tile38 ... | ||||
| // | ||||
| // Description : tile38 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-18 3:45 下午 | ||||
| package tile38 | ||||
							
								
								
									
										185
									
								
								tool/json2go/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								tool/json2go/parser.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | ||||
| // Package json2go ... | ||||
| // | ||||
| // Description : json2go ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-09 3:44 下午 | ||||
| package json2go | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/util" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/tidwall/gjson" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// structName 结构体名称 | ||||
| 	structName = "Automatic" | ||||
| ) | ||||
|  | ||||
| // NewJSON2GO ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:13 下午 2021/11/9 | ||||
| func NewJSON2GO(name string) *JSON2GO { | ||||
| 	if len(name) == 0 { | ||||
| 		name = structName | ||||
| 	} | ||||
| 	return &JSON2GO{ | ||||
| 		structName: name, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // JSON2GO ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 6:12 下午 2021/11/9 | ||||
| type JSON2GO struct { | ||||
| 	structName string | ||||
| 	result     string | ||||
| } | ||||
|  | ||||
| // Parse ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 3:44 下午 2021/11/9 | ||||
| func (jg *JSON2GO) Parse(inputJSON string) (string, error) { | ||||
| 	if !gjson.Valid(inputJSON) { | ||||
| 		return "", errors.New("input json is invalid") | ||||
| 	} | ||||
| 	parseResult := gjson.Parse(inputJSON) | ||||
| 	if parseResult.IsArray() { | ||||
| 		jg.append("type " + jg.structName + " [] \n") | ||||
| 		jg.parseArray("", parseResult) | ||||
| 	} else { | ||||
| 		jg.append("type " + jg.structName + " struct { \n") | ||||
| 		jg.parseObject("", parseResult) | ||||
| 	} | ||||
| 	jg.append("}") | ||||
| 	return jg.result, nil | ||||
| } | ||||
|  | ||||
| // parseArray 解析array | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:37 下午 2021/11/9 | ||||
| func (jg *JSON2GO) parseArray(key string, parseResult gjson.Result) { | ||||
| 	// 先遍历一遍确认所有数据类型都相同 | ||||
| 	dataType := "" | ||||
| 	if len(parseResult.Array()) > 0 { | ||||
| 		for _, item := range parseResult.Array() { | ||||
| 			if len(dataType) == 0 { | ||||
| 				dataType = jg.getDataType(item) | ||||
| 				continue | ||||
| 			} | ||||
| 			currentType := jg.getDataType(item) | ||||
| 			if currentType != dataType { | ||||
| 				if (dataType == "int64" && currentType == "float64") || (dataType == "float64" && currentType == "int64") { | ||||
| 					dataType = "float64" | ||||
| 					continue | ||||
| 				} | ||||
| 				// 不是所有数据类型都一致 | ||||
| 				if len(key) == 0 { | ||||
| 					jg.result += "interface{}" | ||||
| 					return | ||||
| 				} | ||||
| 				jg.append(jg.buildField("[]interface{}", key)) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		dataType = "interface{}" | ||||
| 	} | ||||
| 	// 对象,重新 | ||||
| 	if dataType == "object" { | ||||
| 		instance := NewJSON2GO("") | ||||
| 		r, _ := instance.Parse(parseResult.Array()[0].String()) | ||||
| 		dataType = strings.Replace(strings.Replace(r, "type", "", 1), "Automatic", "", 1) | ||||
| 	} | ||||
|  | ||||
| 	// 所有数据类型都一致 | ||||
| 	if len(key) == 0 { | ||||
| 		jg.append("[]" + dataType) | ||||
| 	} else { | ||||
| 		jg.append(jg.buildField("[]"+dataType, key)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // parseObject 解析object | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:37 下午 2021/11/9 | ||||
| func (jg *JSON2GO) parseObject(key string, parseResult gjson.Result) string { | ||||
| 	if len(key) > 0 { | ||||
| 		jg.result += util.SnakeCaseToCamel(key) + " struct { \n" | ||||
| 	} | ||||
| 	for k, v := range parseResult.Map() { | ||||
| 		if v.IsObject() { | ||||
| 			jg.parseObject(k, v) | ||||
| 		} else if v.IsArray() { | ||||
| 			jg.parseArray(k, v) | ||||
| 		} else { | ||||
| 			jg.append(jg.buildField(jg.getDataType(v), k)) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(key) > 0 { | ||||
| 		jg.append(" } `json:\"" + key + "\"`\n") | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| // getDataType 获取数据类型 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 8:14 下午 2021/11/9 | ||||
| func (jg *JSON2GO) getDataType(val gjson.Result) string { | ||||
| 	switch val.Type { | ||||
| 	case gjson.True: | ||||
| 		fallthrough | ||||
| 	case gjson.False: | ||||
| 		return "bool" | ||||
| 	case gjson.Null: | ||||
| 		return "map[string]interface{}" | ||||
| 	case gjson.String: | ||||
| 		return "string" | ||||
| 	case gjson.Number: | ||||
| 		tmpVal := fmt.Sprintf("%v", val.Num) | ||||
| 		if strings.Contains(tmpVal, ".") { | ||||
| 			return "float64" | ||||
| 		} | ||||
| 		return "int64" | ||||
| 	case gjson.JSON: | ||||
| 		return "object" | ||||
| 	default: | ||||
| 		return "interface{}" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // buildField 构建字段 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 9:20 下午 2021/11/9 | ||||
| func (jq *JSON2GO) buildField(fieldType string, jsonTag string) string { | ||||
| 	return util.SnakeCaseToCamel(jsonTag) + " " + fieldType + " `json:\"" + jsonTag + "\"`\n" | ||||
| } | ||||
|  | ||||
| // append 构建result | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 9:19 下午 2021/11/9 | ||||
| func (jq *JSON2GO) append(appendStr string) { | ||||
| 	jq.result += appendStr | ||||
| } | ||||
							
								
								
									
										59
									
								
								tool/sql2go/dao_tpl.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								tool/sql2go/dao_tpl.tpl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // Package {PACKAGE} ... | ||||
| // | ||||
| // Description : {PACKAGE} ... | ||||
| package {PACKAGE} | ||||
|  | ||||
| import ( | ||||
|     "gorm.io/gorm" | ||||
|     "errors" | ||||
| ) | ||||
|  | ||||
| // {DATA_STRUCT_NAME} 数据库表的数据结构 | ||||
| {DATA_STRUCT} | ||||
|  | ||||
| // New{DATA_STRUCT_DAO} 获取DAO实例 | ||||
| func New{DATA_STRUCT_DAO}() *{DATA_STRUCT_DAO} { | ||||
|     return &{DATA_STRUCT_DAO}{ | ||||
|         table : "{DB_TABLE_NAME}", | ||||
|     } | ||||
| } | ||||
|  | ||||
| // {DATA_STRUCT_DAO} sql2go tool generate | ||||
| type {DATA_STRUCT_DAO} struct { | ||||
|     table string | ||||
| } | ||||
|  | ||||
| // GetDetailBy{PRIMARY_KEY} 根据主键ID获取详情 | ||||
| func ({DAO_RECEIVER} *{DATA_STRUCT_DAO}) GetDetailBy{PRIMARY_KEY}(dbInstance *gorm.DB, {PRIMARY_KEY} {PRIMARY_KEY_TYPE}) (*{DATA_STRUCT_NAME}, error) { | ||||
|     var ( | ||||
|         err error | ||||
|         detail {DATA_STRUCT_NAME} | ||||
|     ) | ||||
|     if err = dbInstance.Table({DAO_RECEIVER}.table).Where("{PRIMARY_KEY_FIELD} = ?", {PRIMARY_KEY}).Limit(1).First(&detail).Error; nil != err { | ||||
|         return nil, err | ||||
|     } | ||||
|     return &detail, nil | ||||
| } | ||||
|  | ||||
| // GetList 获取数据列表 | ||||
| func ({DAO_RECEIVER} *{DATA_STRUCT_DAO}) GetList(dbInstance *gorm.DB, condition map[string]interface{}, limit int, offset int) ([]{DATA_STRUCT_NAME}, error) { | ||||
|     if nil == condition { | ||||
|         condition = make(map[string]interface{}) | ||||
|     } | ||||
|     var ( | ||||
|         err error | ||||
|         list []{DATA_STRUCT_NAME} | ||||
|     ) | ||||
|     if err = dbInstance.Table({DAO_RECEIVER}.table).Where(condition).Limit(limit).Offset(offset).Find(&list).Error; nil != err { | ||||
|         return make([]{DATA_STRUCT_NAME}, 0), err | ||||
|     } | ||||
|     return list, nil | ||||
| } | ||||
|  | ||||
| // Create 创建数据 | ||||
| func ({DAO_RECEIVER} *{DATA_STRUCT_DAO}) Create(dbInstance *gorm.DB, data *{DATA_STRUCT_NAME}) error { | ||||
|     if nil == data { | ||||
|         return  errors.New("data is nil") | ||||
|     } | ||||
|     return dbInstance.Table({DAO_RECEIVER}.table).Create(data).Error | ||||
| } | ||||
							
								
								
									
										59
									
								
								tool/sql2go/generate_dao.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								tool/sql2go/generate_dao.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // Package sql2go... | ||||
| // | ||||
| // Description : sql2go... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-17 10:14 上午 | ||||
| package sql2go | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/util" | ||||
| ) | ||||
|  | ||||
| // GenerateDao 根据sql自动生成dao | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 10:15 上午 2021/11/17 | ||||
| func GenerateDao(sql string, packageName string) (string, error) { | ||||
| 	if len(packageName) == 0 { | ||||
| 		packageName = "dao" | ||||
| 	} | ||||
| 	dataStruct, basic, err := ParseCreateTableSql(sql) | ||||
| 	if nil != err { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	// 读入模板 | ||||
| 	tplByte, _ := util.ReadFileContent("dao_tpl.tpl") | ||||
| 	tpl := string(tplByte) | ||||
| 	replaceTable := map[string]string{ | ||||
| 		"{PACKAGE}":          packageName, | ||||
| 		"{DATA_STRUCT_DAO}":  basic.ModelStruct + "Dao", | ||||
| 		"{DATA_STRUCT_NAME}": basic.ModelStruct, | ||||
| 		"{DATA_STRUCT}":      dataStruct, | ||||
| 		"{DAO_RECEIVER}":     getDaoReceiver(basic.TableName), | ||||
| 		"{DB_TABLE_NAME}":    basic.TableName, | ||||
| 		"{PRIMARY_KEY}":      "ID", | ||||
| 		"{PRIMARY_KEY_TYPE}": basic.PrimaryFieldType, | ||||
| 	} | ||||
|  | ||||
| 	for oldVal, newVal := range replaceTable { | ||||
| 		tpl = strings.ReplaceAll(tpl, oldVal, newVal) | ||||
| 	} | ||||
| 	return tpl, nil | ||||
| } | ||||
|  | ||||
| func getDaoReceiver(tableName string) string { | ||||
| 	nameArr := strings.Split(tableName, "_") | ||||
| 	result := "" | ||||
| 	for _, item := range nameArr { | ||||
| 		if len(item) > 0 { | ||||
| 			result += string([]byte(item)[0]) | ||||
| 		} | ||||
| 	} | ||||
| 	result += "d" | ||||
| 	return result | ||||
| } | ||||
| @ -20,23 +20,44 @@ const ( | ||||
| 	CreateSQLColumnTPL = "{FIELD} {TYPE} `json:\"{JSON_TAG}\" gorm:\"column:{COLUMN};default:{DEFAULT_VALUE};{NOT_NULL}\"` // {COMMENT}" | ||||
| ) | ||||
|  | ||||
| // BasicTableInfo ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 11:47 上午 2021/11/17 | ||||
| type BasicTableInfo struct { | ||||
| 	TableName        string | ||||
| 	ModelStruct      string | ||||
| 	PrimaryField     string | ||||
| 	PrimaryFieldType string | ||||
| } | ||||
|  | ||||
| // ParseCreateTableSql 解析建表sql | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:49 下午 2021/10/25 | ||||
| func ParseCreateTableSql(sql string) (string, error) { | ||||
| func ParseCreateTableSql(sql string) (string, *BasicTableInfo, error) { | ||||
| 	var ( | ||||
| 		stmt  sqlparser.Statement | ||||
| 		err   error | ||||
| 		basic *BasicTableInfo | ||||
| 	) | ||||
| 	sql = strings.ReplaceAll(strings.ToUpper(sql), "CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP") | ||||
| 	basic = &BasicTableInfo{ | ||||
| 		TableName:        "", | ||||
| 		ModelStruct:      "", | ||||
| 		PrimaryField:     "ID", | ||||
| 		PrimaryFieldType: "", | ||||
| 	} | ||||
| 	sql = strings.ReplaceAll(strings.ReplaceAll(sql, "CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP"), "current_timestamp()", "CURRENT_TIMESTAMP") | ||||
| 	if stmt, err = sqlparser.ParseStrictDDL(sql); nil != err { | ||||
| 		return "", err | ||||
| 		return "", nil, err | ||||
| 	} | ||||
|  | ||||
| 	r := stmt.(*sqlparser.DDL) | ||||
| 	structResult := "type " + util.SnakeCaseToCamel(sqlparser.String(r.NewName)) + " struct { \n" | ||||
| 	basic.TableName = sqlparser.String(r.NewName) | ||||
| 	basic.ModelStruct = util.SnakeCaseToCamel(basic.TableName) | ||||
| 	structResult := "type " + basic.ModelStruct + " struct { \n" | ||||
|  | ||||
| 	for _, item := range r.TableSpec.Columns { | ||||
| 		data := map[string]string{ | ||||
| @ -47,6 +68,9 @@ func ParseCreateTableSql(sql string) (string, error) { | ||||
| 			"{COMMENT}":       item.Name.String() + " " + string(item.Type.Comment.Val), | ||||
| 			"{TYPE}":          sqlTypeMap[item.Type.Type], | ||||
| 		} | ||||
| 		if data["{FIELD}"] == "ID" { | ||||
| 			basic.PrimaryFieldType = data["{TYPE}"] | ||||
| 		} | ||||
| 		if item.Type.NotNull { | ||||
| 			data["{NOT_NULL}"] = "NOT NULL" | ||||
| 		} | ||||
| @ -60,5 +84,5 @@ func ParseCreateTableSql(sql string) (string, error) { | ||||
| 		structResult += val + "\n" | ||||
| 	} | ||||
| 	structResult = structResult + "}" | ||||
| 	return structResult, nil | ||||
| 	return structResult, basic, nil | ||||
| } | ||||
|  | ||||
							
								
								
									
										26
									
								
								util/ip.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								util/ip.go
									
									
									
									
									
								
							| @ -7,7 +7,10 @@ | ||||
| // Date : 2021-03-09 5:56 下午 | ||||
| package util | ||||
|  | ||||
| import "net" | ||||
| import ( | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| // GetHostIP 获取本机IP地址 | ||||
| // | ||||
| @ -27,3 +30,24 @@ func GetHostIP() string { | ||||
| 	} | ||||
| 	return hostIP | ||||
| } | ||||
|  | ||||
| // GetRemoteIp 获取远端IP | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:35 下午 2021/11/22 | ||||
| func GetRemoteIp(req *http.Request) string { | ||||
|  | ||||
| 	// Try via request | ||||
|  | ||||
| 	ip, _, err := net.SplitHostPort(req.RemoteAddr) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "::1" | ||||
| 	} | ||||
| 	userIP := net.ParseIP(ip) | ||||
| 	if userIP == nil { | ||||
| 		return "::1" | ||||
| 	} | ||||
| 	return userIP.String() | ||||
| } | ||||
|  | ||||
							
								
								
									
										55
									
								
								util/json.go
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								util/json.go
									
									
									
									
									
								
							| @ -10,7 +10,10 @@ package util | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| // JSONUnmarshalWithNumber 解析json | ||||
| @ -34,3 +37,55 @@ func JSONUnmarshalWithNumberForIOReader(ioReader io.ReadCloser, receiver interfa | ||||
| 	decoder.UseNumber() | ||||
| 	return decoder.Decode(receiver) | ||||
| } | ||||
|  | ||||
| // JSONConsoleOutput ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:45 下午 2021/11/5 | ||||
| func JSONConsoleOutput(data interface{}) { | ||||
| 	var out bytes.Buffer | ||||
| 	switch reflect.TypeOf(data).Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		fallthrough | ||||
| 	case reflect.Array: | ||||
| 		fallthrough | ||||
| 	case reflect.Map: | ||||
| 		fallthrough | ||||
| 	case reflect.Ptr: | ||||
| 		byteData, _ := json.Marshal(data) | ||||
| 		_ = json.Indent(&out, []byte(string(byteData)+"\n"), "", "\t") | ||||
| 		_, _ = out.WriteTo(os.Stdout) | ||||
| 		return | ||||
| 	case reflect.Int: | ||||
| 		fallthrough | ||||
| 	case reflect.Int8: | ||||
| 		fallthrough | ||||
| 	case reflect.Int16: | ||||
| 		fallthrough | ||||
| 	case reflect.Int32: | ||||
| 		fallthrough | ||||
| 	case reflect.Int64: | ||||
| 		fallthrough | ||||
| 	case reflect.Uint: | ||||
| 		fallthrough | ||||
| 	case reflect.Uint8: | ||||
| 		fallthrough | ||||
| 	case reflect.Uint16: | ||||
| 		fallthrough | ||||
| 	case reflect.Uint32: | ||||
| 		fallthrough | ||||
| 	case reflect.Uint64: | ||||
| 		fallthrough | ||||
| 	case reflect.Float32: | ||||
| 		fallthrough | ||||
| 	case reflect.Float64: | ||||
| 		fallthrough | ||||
| 	case reflect.String: | ||||
| 		_ = json.Indent(&out, []byte(fmt.Sprintf("%v\n", data)), "", "\t") | ||||
| 		_, _ = out.WriteTo(os.Stdout) | ||||
| 		return | ||||
| 	default: | ||||
| 		fmt.Println("") | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										209
									
								
								util/map.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								util/map.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,209 @@ | ||||
| // Package util ... | ||||
| // | ||||
| // Description : 从map中读取数据 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-16 4:28 下午 | ||||
| package util | ||||
|  | ||||
| import ( | ||||
| 	"git.zhangdeman.cn/zhangdeman/gopkg/convert" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| // Exist 检测一个key在map中是否存在 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:52 下午 2021/11/16 | ||||
| func Exist(source map[interface{}]interface{}, key interface{}) bool { | ||||
| 	if nil == source { | ||||
| 		return false | ||||
| 	} | ||||
| 	if _, exist := source[key]; !exist { | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // GetInt 获取int值 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:30 下午 2021/11/16 | ||||
| func GetInt(source map[interface{}]interface{}, key interface{}, defaultVal int) int { | ||||
| 	var result int | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetInt8 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:59 下午 2021/11/16 | ||||
| func GetInt8(source map[interface{}]interface{}, key interface{}, defaultVal int8) int8 { | ||||
| 	var result int8 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetInt16 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:59 下午 2021/11/16 | ||||
| func GetInt16(source map[interface{}]interface{}, key interface{}, defaultVal int16) int16 { | ||||
| 	var result int16 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetInt32 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:00 下午 2021/11/16 | ||||
| func GetInt32(source map[interface{}]interface{}, key interface{}, defaultVal int32) int32 { | ||||
| 	var result int32 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetInt64 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:00 下午 2021/11/16 | ||||
| func GetInt64(source map[interface{}]interface{}, key interface{}, defaultVal int64) int64 { | ||||
| 	var result int64 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetUint ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:01 下午 2021/11/16 | ||||
| func GetUint(source map[interface{}]interface{}, key interface{}, defaultVal uint) uint { | ||||
| 	var result uint | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetUint8 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:01 下午 2021/11/16 | ||||
| func GetUint8(source map[interface{}]interface{}, key interface{}, defaultVal uint8) uint8 { | ||||
| 	var result uint8 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetUint16 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:02 下午 2021/11/16 | ||||
| func GetUint16(source map[interface{}]interface{}, key interface{}, defaultVal uint16) uint16 { | ||||
| 	var result uint16 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetUint32 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:02 下午 2021/11/16 | ||||
| func GetUint32(source map[interface{}]interface{}, key interface{}, defaultVal uint32) uint32 { | ||||
| 	var result uint32 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetUint64 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:03 下午 2021/11/16 | ||||
| func GetUint64(source map[interface{}]interface{}, key interface{}, defaultVal uint64) uint64 { | ||||
| 	var result uint64 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetFloat32 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:03 下午 2021/11/16 | ||||
| func GetFloat32(source map[interface{}]interface{}, key interface{}, defaultVal float32) float32 { | ||||
| 	var result float32 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetFloat64 ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:04 下午 2021/11/16 | ||||
| func GetFloat64(source map[interface{}]interface{}, key interface{}, defaultVal float64) float64 { | ||||
| 	var result float64 | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetString ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 5:07 下午 2021/11/16 | ||||
| func GetString(source map[interface{}]interface{}, key interface{}, defaultVal string) string { | ||||
| 	var result string | ||||
| 	if err := GetDataWithReceiver(source, key, &result); nil != err { | ||||
| 		return defaultVal | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // GetDataWithReceiver 使用制定的数据指针接受结果 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 4:54 下午 2021/11/16 | ||||
| func GetDataWithReceiver(source map[interface{}]interface{}, key interface{}, receiver interface{}) error { | ||||
| 	if !Exist(source, key) { | ||||
| 		return errors.New("key is not found") | ||||
| 	} | ||||
| 	return convert.ConvertAssign(receiver, source[key]) | ||||
| } | ||||
| @ -54,6 +54,9 @@ func Md5(str string) string { | ||||
| // | ||||
| // Date : 4:58 下午 2021/10/25 | ||||
| func SnakeCaseToCamel(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	builder := strings.Builder{} | ||||
| 	index := 0 | ||||
| 	if str[0] >= 'a' && str[0] <= 'z' { | ||||
| @ -68,6 +71,11 @@ func SnakeCaseToCamel(str string) string { | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		// 将ID转为大写 | ||||
| 		if str[i] == 'd' && i-1 >= 0 && (str[i-1] == 'i' || str[i-1] == 'I') && (i+1 == len(str) || i+1 < len(str) && str[i+1] == '_') { | ||||
| 			builder.WriteByte('d' - ('a' - 'A')) | ||||
| 			continue | ||||
| 		} | ||||
| 		builder.WriteByte(str[i]) | ||||
| 	} | ||||
| 	return builder.String() | ||||
|  | ||||
							
								
								
									
										89
									
								
								util/url.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								util/url.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| // Package util... | ||||
| // | ||||
| // Description : util... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2021-11-04 2:38 下午 | ||||
| package util | ||||
|  | ||||
| import ( | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // URLParseResult url解析 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:51 下午 2021/11/4 | ||||
| type URLParseResult struct { | ||||
| 	Scheme    string            `json:"scheme"` | ||||
| 	Domain    string            `json:"domain"` | ||||
| 	URI       string            `json:"uri"` | ||||
| 	Parameter map[string]string `json:"parameter"` | ||||
| } | ||||
|  | ||||
| // URLEncode ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:39 下午 2021/11/4 | ||||
| func URLEncode(inputURL string) string { | ||||
| 	return url.QueryEscape(inputURL) | ||||
| } | ||||
|  | ||||
| // URLDecode ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:39 下午 2021/11/4 | ||||
| func URLDecode(inputURL string) (string, error) { | ||||
| 	return url.QueryUnescape(inputURL) | ||||
| } | ||||
|  | ||||
| // URLParse url解析 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:39 下午 2021/11/4 | ||||
| func URLParse(inputURL string) (*URLParseResult, error) { | ||||
| 	var ( | ||||
| 		parseResult *url.URL | ||||
| 		err         error | ||||
| 	) | ||||
| 	if parseResult, err = url.Parse(inputURL); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	detail := &URLParseResult{ | ||||
| 		Scheme:    parseResult.Scheme, | ||||
| 		Domain:    parseResult.Host, | ||||
| 		URI:       parseResult.Path, | ||||
| 		Parameter: make(map[string]string), | ||||
| 	} | ||||
| 	for k, v := range parseResult.Query() { | ||||
| 		if len(v) > 1 { | ||||
| 			detail.Parameter[k] = "[" + strings.Join(v, ",") + "]" | ||||
| 		} else { | ||||
| 			detail.Parameter[k] = v[0] | ||||
| 		} | ||||
| 	} | ||||
| 	return detail, nil | ||||
| } | ||||
|  | ||||
| // BuildQueryURL 构建GET链接 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2:43 下午 2021/11/4 | ||||
| func BuildQueryURL(apiURL string, parameter map[string]string) string { | ||||
| 	u := url.Values{} | ||||
| 	for k, v := range parameter { | ||||
| 		u.Set(k, v) | ||||
| 	} | ||||
| 	apiURL = strings.Trim(apiURL, "?") | ||||
| 	if strings.Contains(apiURL, "?") { | ||||
| 		return apiURL + "&" + u.Encode() | ||||
| 	} | ||||
| 	return apiURL + "?" + u.Encode() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user