Compare commits
No commits in common. "master" and "develop" have entirely different histories.
.gitignore
balance
cmd
consistent_hash
demo
easylock
excel
gin
git_hook
go.modgo.sumjson_tool
logger/wrapper
middleware
apollo
etcd
define.godelete.godelete_test.goinit.golease.golease_test.gostring.gostring_test.gowatch.gowatch_test.go
mysql
redis
tile38
oauth
proxy
system
tool
json2go
sql2go
util
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,7 +6,6 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.xlsx
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
@ -18,5 +17,5 @@
|
||||
# vendor/
|
||||
.idea
|
||||
.vscode
|
||||
mail_test.go
|
||||
*_test.go
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
// 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,12 +7,7 @@
|
||||
// Date : 2021-10-19 2:26 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
import "sync"
|
||||
|
||||
// base ...
|
||||
//
|
||||
@ -20,8 +15,7 @@ import (
|
||||
//
|
||||
// Date : 2:26 下午 2021/10/19
|
||||
type base struct {
|
||||
lock *sync.RWMutex
|
||||
severList []*define.ServerNode
|
||||
lock *sync.RWMutex
|
||||
}
|
||||
|
||||
// Lock ...
|
||||
@ -59,53 +53,3 @@ 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
|
||||
}
|
||||
|
@ -13,9 +13,8 @@ package define
|
||||
//
|
||||
// Date : 12:36 下午 2021/10/19
|
||||
type ServerNode struct {
|
||||
HostIP string `json:"host_ip"` // 机器IP
|
||||
Port int `json:"port"` // 机器端口
|
||||
Status int `json:"status"` // 机器状态
|
||||
Weight float64 `json:"weight"` // 机器权重
|
||||
CurrentWeight float64 `json:"current_weight"` // 当前权重
|
||||
HostIP string `json:"host_ip"` // 机器IP
|
||||
Port int `json:"port"` // 机器端口
|
||||
Status int `json:"status"` // 机器状态
|
||||
Weight int `json:"weight"` // 机器权重
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
// 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,7 +8,6 @@
|
||||
package balance
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
@ -20,15 +19,15 @@ import (
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:40 下午 2021/10/19
|
||||
func NewPoll(serverList []*define.ServerNode) (IBalance, error) {
|
||||
func NewPoll(serverList []*define.ServerNode) (*Poll, error) {
|
||||
if nil == serverList || len(serverList) == 0 {
|
||||
return nil, errors.New("server list is empty")
|
||||
}
|
||||
return &Poll{
|
||||
base: base{
|
||||
lock: &sync.RWMutex{},
|
||||
severList: serverList,
|
||||
lock: &sync.RWMutex{},
|
||||
},
|
||||
serverList: serverList,
|
||||
currentServerIndex: 0,
|
||||
}, nil
|
||||
}
|
||||
@ -40,6 +39,7 @@ func NewPoll(serverList []*define.ServerNode) (IBalance, error) {
|
||||
// Date : 12:41 下午 2021/10/19
|
||||
type Poll struct {
|
||||
base
|
||||
serverList []*define.ServerNode
|
||||
currentServerIndex int
|
||||
}
|
||||
|
||||
@ -48,18 +48,21 @@ type Poll struct {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:43 下午 2021/10/19
|
||||
func (p *Poll) GetServerNode(req *http.Request) (*define.ServerNode, error) {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
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()
|
||||
var (
|
||||
serverNode *define.ServerNode
|
||||
)
|
||||
// 循环次数
|
||||
loopTimes := 0
|
||||
for loopTimes < len(p.severList) {
|
||||
for loopTimes < len(p.serverList) {
|
||||
loopTimes++
|
||||
p.currentServerIndex = (p.currentServerIndex + 1) % len(p.severList)
|
||||
if serverNode = p.severList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal {
|
||||
p.currentServerIndex = (p.currentServerIndex + 1) % len(p.serverList)
|
||||
if serverNode = p.serverList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal {
|
||||
continue
|
||||
}
|
||||
break
|
||||
@ -71,3 +74,57 @@ func (p *Poll) GetServerNode(req *http.Request) (*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
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
// Package balance...
|
||||
//
|
||||
// Description : balance...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-19 2:39 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// TestPoll_GetServerNode 轮询模式负载均衡单测
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:39 下午 2021/10/19
|
||||
func TestPoll_GetServerNode(t *testing.T) {
|
||||
t.Run("轮询模式负载均衡单元测试", func(t *testing.T) {
|
||||
p, _ := NewPoll([]*define.ServerNode{
|
||||
{HostIP: "127.0.0.1", Port: 80, Status: 0, Weight: 0},
|
||||
{HostIP: "127.0.0.1", Port: 81, Status: 0, Weight: 0},
|
||||
{HostIP: "127.0.0.1", Port: 82, Status: 0, Weight: 0},
|
||||
})
|
||||
for i := 0; i < 100; i++ {
|
||||
got, err := p.GetServerNode()
|
||||
if nil != err {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s:%d\n", got.HostIP, got.Port)
|
||||
}
|
||||
})
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// 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"`
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// Package cmd...
|
||||
//
|
||||
// Description : cmd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-12 2:28 下午
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestExecute ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:28 下午 2021/11/12
|
||||
func TestExecute(t *testing.T) {
|
||||
r := Execute(Config{
|
||||
WorkDir: "/tmp",
|
||||
Command: "ls",
|
||||
Script: "",
|
||||
ParameterList: []Parameter{{"", "-l"}, {"", "-a"}},
|
||||
})
|
||||
fmt.Println(string(r.Output), r.Err, r.ExecuteCommand, r.WorkDir)
|
||||
r = Execute(Config{
|
||||
WorkDir: "",
|
||||
Command: "sh",
|
||||
Script: "test.sh",
|
||||
ParameterList: []Parameter{},
|
||||
})
|
||||
fmt.Println(string(r.Output), r.Err, r.ExecuteCommand, r.WorkDir)
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
// 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...)
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
// 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
|
||||
)
|
586
demo/context.go
586
demo/context.go
@ -1,586 +0,0 @@
|
||||
// Package demo ...
|
||||
//
|
||||
// Description : demo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-12-02 12:43 下午
|
||||
package demo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package context defines the Context type, which carries deadlines,
|
||||
// cancellation signals, and other request-scoped values across API boundaries
|
||||
// and between processes.
|
||||
//
|
||||
// Incoming requests to a server should create a Context, and outgoing
|
||||
// calls to servers should accept a Context. The chain of function
|
||||
// calls between them must propagate the Context, optionally replacing
|
||||
// it with a derived Context created using WithCancel, WithDeadline,
|
||||
// WithTimeout, or WithValue. When a Context is canceled, all
|
||||
// Contexts derived from it are also canceled.
|
||||
//
|
||||
// The WithCancel, WithDeadline, and WithTimeout functions take a
|
||||
// Context (the parent) and return a derived Context (the child) and a
|
||||
// CancelFunc. Calling the CancelFunc cancels the child and its
|
||||
// children, removes the parent's reference to the child, and stops
|
||||
// any associated timers. Failing to call the CancelFunc leaks the
|
||||
// child and its children until the parent is canceled or the timer
|
||||
// fires. The go vet tool checks that CancelFuncs are used on all
|
||||
// control-flow paths.
|
||||
//
|
||||
// Programs that use Contexts should follow these rules to keep interfaces
|
||||
// consistent across packages and enable static analysis tools to check context
|
||||
// propagation:
|
||||
//
|
||||
// Do not store Contexts inside a struct type; instead, pass a Context
|
||||
// explicitly to each function that needs it. The Context should be the first
|
||||
// parameter, typically named ctx:
|
||||
//
|
||||
// func DoSomething(ctx context.Context, arg Arg) error {
|
||||
// // ... use ctx ...
|
||||
// }
|
||||
//
|
||||
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
|
||||
// if you are unsure about which Context to use.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
// APIs, not for passing optional parameters to functions.
|
||||
//
|
||||
// The same Context may be passed to functions running in different goroutines;
|
||||
// Contexts are safe for simultaneous use by multiple goroutines.
|
||||
//
|
||||
// See https://blog.golang.org/context for example code for a server that uses
|
||||
// Contexts.
|
||||
|
||||
// A Context carries a deadline, a cancellation signal, and other values across
|
||||
// API boundaries.
|
||||
//
|
||||
// Context's methods may be called by multiple goroutines simultaneously.
|
||||
type Context interface {
|
||||
// Deadline returns the time when work done on behalf of this context
|
||||
// should be canceled. Deadline returns ok==false when no deadline is
|
||||
// set. Successive calls to Deadline return the same results.
|
||||
Deadline() (deadline time.Time, ok bool)
|
||||
|
||||
// Done returns a channel that's closed when work done on behalf of this
|
||||
// context should be canceled. Done may return nil if this context can
|
||||
// never be canceled. Successive calls to Done return the same value.
|
||||
// The close of the Done channel may happen asynchronously,
|
||||
// after the cancel function returns.
|
||||
//
|
||||
// WithCancel arranges for Done to be closed when cancel is called;
|
||||
// WithDeadline arranges for Done to be closed when the deadline
|
||||
// expires; WithTimeout arranges for Done to be closed when the timeout
|
||||
// elapses.
|
||||
//
|
||||
// Done is provided for use in select statements:
|
||||
//
|
||||
// // Stream generates values with DoSomething and sends them to out
|
||||
// // until DoSomething returns an error or ctx.Done is closed.
|
||||
// func Stream(ctx context.Context, out chan<- Value) error {
|
||||
// for {
|
||||
// v, err := DoSomething(ctx)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return ctx.Err()
|
||||
// case out <- v:
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// See https://blog.golang.org/pipelines for more examples of how to use
|
||||
// a Done channel for cancellation.
|
||||
Done() <-chan struct{}
|
||||
|
||||
// If Done is not yet closed, Err returns nil.
|
||||
// If Done is closed, Err returns a non-nil error explaining why:
|
||||
// Canceled if the context was canceled
|
||||
// or DeadlineExceeded if the context's deadline passed.
|
||||
// After Err returns a non-nil error, successive calls to Err return the same error.
|
||||
Err() error
|
||||
|
||||
// Value returns the value associated with this context for key, or nil
|
||||
// if no value is associated with key. Successive calls to Value with
|
||||
// the same key returns the same result.
|
||||
//
|
||||
// Use context values only for request-scoped data that transits
|
||||
// processes and API boundaries, not for passing optional parameters to
|
||||
// functions.
|
||||
//
|
||||
// A key identifies a specific value in a Context. Functions that wish
|
||||
// to store values in Context typically allocate a key in a global
|
||||
// variable then use that key as the argument to context.WithValue and
|
||||
// Context.Value. A key can be any type that supports equality;
|
||||
// packages should define keys as an unexported type to avoid
|
||||
// collisions.
|
||||
//
|
||||
// Packages that define a Context key should provide type-safe accessors
|
||||
// for the values stored using that key:
|
||||
//
|
||||
// // Package user defines a User type that's stored in Contexts.
|
||||
// package user
|
||||
//
|
||||
// import "context"
|
||||
//
|
||||
// // User is the type of value stored in the Contexts.
|
||||
// type User struct {...}
|
||||
//
|
||||
// // key is an unexported type for keys defined in this package.
|
||||
// // This prevents collisions with keys defined in other packages.
|
||||
// type key int
|
||||
//
|
||||
// // userKey is the key for user.User values in Contexts. It is
|
||||
// // unexported; clients use user.NewContext and user.FromContext
|
||||
// // instead of using this key directly.
|
||||
// var userKey key
|
||||
//
|
||||
// // NewContext returns a new Context that carries value u.
|
||||
// func NewContext(ctx context.Context, u *User) context.Context {
|
||||
// return context.WithValue(ctx, userKey, u)
|
||||
// }
|
||||
//
|
||||
// // FromContext returns the User value stored in ctx, if any.
|
||||
// func FromContext(ctx context.Context) (*User, bool) {
|
||||
// u, ok := ctx.Value(userKey).(*User)
|
||||
// return u, ok
|
||||
// }
|
||||
Value(key interface{}) interface{}
|
||||
}
|
||||
|
||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
||||
var Canceled = errors.New("context canceled")
|
||||
|
||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
||||
// deadline passes.
|
||||
var DeadlineExceeded error = deadlineExceededError{}
|
||||
|
||||
type deadlineExceededError struct{}
|
||||
|
||||
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
|
||||
func (deadlineExceededError) Timeout() bool { return true }
|
||||
func (deadlineExceededError) Temporary() bool { return true }
|
||||
|
||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||
// struct{}, since vars of this type must have distinct addresses.
|
||||
type emptyCtx int
|
||||
|
||||
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (*emptyCtx) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyCtx) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*emptyCtx) Value(key interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *emptyCtx) String() string {
|
||||
switch e {
|
||||
case background:
|
||||
return "context.Background"
|
||||
case todo:
|
||||
return "context.TODO"
|
||||
}
|
||||
return "unknown empty Context"
|
||||
}
|
||||
|
||||
var (
|
||||
background = new(emptyCtx)
|
||||
todo = new(emptyCtx)
|
||||
)
|
||||
|
||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
||||
// values, and has no deadline. It is typically used by the main function,
|
||||
// initialization, and tests, and as the top-level Context for incoming
|
||||
// requests.
|
||||
func Background() Context {
|
||||
return background
|
||||
}
|
||||
|
||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
||||
// it's unclear which Context to use or it is not yet available (because the
|
||||
// surrounding function has not yet been extended to accept a Context
|
||||
// parameter).
|
||||
func TODO() Context {
|
||||
return todo
|
||||
}
|
||||
|
||||
// A CancelFunc tells an operation to abandon its work.
|
||||
// A CancelFunc does not wait for the work to stop.
|
||||
// A CancelFunc may be called by multiple goroutines simultaneously.
|
||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
||||
type CancelFunc func()
|
||||
|
||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
||||
// context's Done channel is closed when the returned cancel function is called
|
||||
// or when the parent context's Done channel is closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||
if parent == nil {
|
||||
panic("cannot create context from nil parent")
|
||||
}
|
||||
c := newCancelCtx(parent)
|
||||
propagateCancel(parent, &c)
|
||||
return &c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
|
||||
// newCancelCtx returns an initialized cancelCtx.
|
||||
func newCancelCtx(parent Context) cancelCtx {
|
||||
return cancelCtx{Context: parent}
|
||||
}
|
||||
|
||||
// goroutines counts the number of goroutines ever created; for testing.
|
||||
var goroutines int32
|
||||
|
||||
// propagateCancel arranges for child to be canceled when parent is.
|
||||
func propagateCancel(parent Context, child canceler) {
|
||||
done := parent.Done()
|
||||
if done == nil {
|
||||
return // parent is never canceled
|
||||
}
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
// parent is already canceled
|
||||
child.cancel(false, parent.Err())
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
if p, ok := parentCancelCtx(parent); ok {
|
||||
p.mu.Lock()
|
||||
if p.err != nil {
|
||||
// parent has already been canceled
|
||||
child.cancel(false, p.err)
|
||||
} else {
|
||||
if p.children == nil {
|
||||
p.children = make(map[canceler]struct{})
|
||||
}
|
||||
p.children[child] = struct{}{}
|
||||
}
|
||||
p.mu.Unlock()
|
||||
} else {
|
||||
atomic.AddInt32(&goroutines, +1)
|
||||
go func() {
|
||||
select {
|
||||
case <-parent.Done():
|
||||
child.cancel(false, parent.Err())
|
||||
case <-child.Done():
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// &cancelCtxKey is the key that a cancelCtx returns itself for.
|
||||
var cancelCtxKey int
|
||||
|
||||
// parentCancelCtx returns the underlying *cancelCtx for parent.
|
||||
// It does this by looking up parent.Value(&cancelCtxKey) to find
|
||||
// the innermost enclosing *cancelCtx and then checking whether
|
||||
// parent.Done() matches that *cancelCtx. (If not, the *cancelCtx
|
||||
// has been wrapped in a custom implementation providing a
|
||||
// different done channel, in which case we should not bypass it.)
|
||||
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
||||
done := parent.Done()
|
||||
if done == closedchan || done == nil {
|
||||
return nil, false
|
||||
}
|
||||
p, ok := parent.Value(&cancelCtxKey).(*cancelCtx)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
pdone, _ := p.done.Load().(chan struct{})
|
||||
if pdone != done {
|
||||
return nil, false
|
||||
}
|
||||
return p, true
|
||||
}
|
||||
|
||||
// removeChild removes a context from its parent.
|
||||
func removeChild(parent Context, child canceler) {
|
||||
p, ok := parentCancelCtx(parent)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p.mu.Lock()
|
||||
if p.children != nil {
|
||||
delete(p.children, child)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
}
|
||||
|
||||
// A canceler is a context type that can be canceled directly. The
|
||||
// implementations are *cancelCtx and *timerCtx.
|
||||
type canceler interface {
|
||||
cancel(removeFromParent bool, err error)
|
||||
Done() <-chan struct{}
|
||||
}
|
||||
|
||||
// closedchan is a reusable closed channel.
|
||||
var closedchan = make(chan struct{})
|
||||
|
||||
func init() {
|
||||
close(closedchan)
|
||||
}
|
||||
|
||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
||||
// that implement canceler.
|
||||
type cancelCtx struct {
|
||||
Context
|
||||
|
||||
mu sync.Mutex // protects following fields
|
||||
done atomic.Value // of chan struct{}, created lazily, closed by first cancel call
|
||||
children map[canceler]struct{} // set to nil by the first cancel call
|
||||
err error // set to non-nil by the first cancel call
|
||||
}
|
||||
|
||||
func (c *cancelCtx) Value(key interface{}) interface{} {
|
||||
if key == &cancelCtxKey {
|
||||
return c
|
||||
}
|
||||
return c.Context.Value(key)
|
||||
}
|
||||
|
||||
func (c *cancelCtx) Done() <-chan struct{} {
|
||||
d := c.done.Load()
|
||||
if d != nil {
|
||||
return d.(chan struct{})
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
d = c.done.Load()
|
||||
if d == nil {
|
||||
d = make(chan struct{})
|
||||
c.done.Store(d)
|
||||
}
|
||||
return d.(chan struct{})
|
||||
}
|
||||
|
||||
func (c *cancelCtx) Err() error {
|
||||
c.mu.Lock()
|
||||
err := c.err
|
||||
c.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
type stringer interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
func contextName(c Context) string {
|
||||
if s, ok := c.(stringer); ok {
|
||||
return s.String()
|
||||
}
|
||||
return reflect.TypeOf(c).String()
|
||||
}
|
||||
|
||||
func (c *cancelCtx) String() string {
|
||||
return contextName(c.Context) + ".WithCancel"
|
||||
}
|
||||
|
||||
// cancel closes c.done, cancels each of c's children, and, if
|
||||
// removeFromParent is true, removes c from its parent's children.
|
||||
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
||||
if err == nil {
|
||||
panic("context: internal error: missing cancel error")
|
||||
}
|
||||
c.mu.Lock()
|
||||
if c.err != nil {
|
||||
c.mu.Unlock()
|
||||
return // already canceled
|
||||
}
|
||||
c.err = err
|
||||
d, _ := c.done.Load().(chan struct{})
|
||||
if d == nil {
|
||||
c.done.Store(closedchan)
|
||||
} else {
|
||||
close(d)
|
||||
}
|
||||
for child := range c.children {
|
||||
// NOTE: acquiring the child's lock while holding parent's lock.
|
||||
child.cancel(false, err)
|
||||
}
|
||||
c.children = nil
|
||||
c.mu.Unlock()
|
||||
|
||||
if removeFromParent {
|
||||
removeChild(c.Context, c)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
||||
// context's Done channel is closed when the deadline expires, when the returned
|
||||
// cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
|
||||
if parent == nil {
|
||||
panic("cannot create context from nil parent")
|
||||
}
|
||||
if cur, ok := parent.Deadline(); ok && cur.Before(d) {
|
||||
// The current deadline is already sooner than the new one.
|
||||
return WithCancel(parent)
|
||||
}
|
||||
c := &timerCtx{
|
||||
cancelCtx: newCancelCtx(parent),
|
||||
deadline: d,
|
||||
}
|
||||
propagateCancel(parent, c)
|
||||
dur := time.Until(d)
|
||||
if dur <= 0 {
|
||||
c.cancel(true, DeadlineExceeded) // deadline has already passed
|
||||
return c, func() { c.cancel(false, Canceled) }
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.err == nil {
|
||||
c.timer = time.AfterFunc(dur, func() {
|
||||
c.cancel(true, DeadlineExceeded)
|
||||
})
|
||||
}
|
||||
return c, func() { c.cancel(true, Canceled) }
|
||||
}
|
||||
|
||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
||||
// implement Done and Err. It implements cancel by stopping its timer then
|
||||
// delegating to cancelCtx.cancel.
|
||||
type timerCtx struct {
|
||||
cancelCtx
|
||||
timer *time.Timer // Under cancelCtx.mu.
|
||||
|
||||
deadline time.Time
|
||||
}
|
||||
|
||||
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return c.deadline, true
|
||||
}
|
||||
|
||||
func (c *timerCtx) String() string {
|
||||
return contextName(c.cancelCtx.Context) + ".WithDeadline(" +
|
||||
c.deadline.String() + " [" +
|
||||
time.Until(c.deadline).String() + "])"
|
||||
}
|
||||
|
||||
func (c *timerCtx) cancel(removeFromParent bool, err error) {
|
||||
c.cancelCtx.cancel(false, err)
|
||||
if removeFromParent {
|
||||
// Remove this timerCtx from its parent cancelCtx's children.
|
||||
removeChild(c.cancelCtx.Context, c)
|
||||
}
|
||||
c.mu.Lock()
|
||||
if c.timer != nil {
|
||||
c.timer.Stop()
|
||||
c.timer = nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete:
|
||||
//
|
||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
||||
// return slowOperation(ctx)
|
||||
// }
|
||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
||||
return WithDeadline(parent, time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
// WithValue returns a copy of parent in which the value associated with key is
|
||||
// val.
|
||||
//
|
||||
// Use context Values only for request-scoped data that transits processes and
|
||||
// APIs, not for passing optional parameters to functions.
|
||||
//
|
||||
// The provided key must be comparable and should not be of type
|
||||
// string or any other built-in type to avoid collisions between
|
||||
// packages using context. Users of WithValue should define their own
|
||||
// types for keys. To avoid allocating when assigning to an
|
||||
// interface{}, context keys often have concrete type
|
||||
// struct{}. Alternatively, exported context key variables' static
|
||||
// type should be a pointer or interface.
|
||||
func WithValue(parent Context, key, val interface{}) Context {
|
||||
if parent == nil {
|
||||
panic("cannot create context from nil parent")
|
||||
}
|
||||
if key == nil {
|
||||
panic("nil key")
|
||||
}
|
||||
if !reflect.TypeOf(key).Comparable() {
|
||||
panic("key is not comparable")
|
||||
}
|
||||
return &valueCtx{parent, key, val}
|
||||
}
|
||||
|
||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
||||
// delegates all other calls to the embedded Context.
|
||||
type valueCtx struct {
|
||||
Context
|
||||
key, val interface{}
|
||||
}
|
||||
|
||||
// stringify tries a bit to stringify v, without using fmt, since we don't
|
||||
// want context depending on the unicode tables. This is only used by
|
||||
// *valueCtx.String().
|
||||
func stringify(v interface{}) string {
|
||||
switch s := v.(type) {
|
||||
case stringer:
|
||||
return s.String()
|
||||
case string:
|
||||
return s
|
||||
}
|
||||
return "<not Stringer>"
|
||||
}
|
||||
|
||||
func (c *valueCtx) String() string {
|
||||
return contextName(c.Context) + ".WithValue(type " +
|
||||
reflect.TypeOf(c.key).String() +
|
||||
", val " + stringify(c.val) + ")"
|
||||
}
|
||||
|
||||
func (c *valueCtx) Value(key interface{}) interface{} {
|
||||
if c.key == key {
|
||||
return c.val
|
||||
}
|
||||
return c.Context.Value(key)
|
||||
}
|
||||
|
||||
// ======================== 以上为 context.go 源码
|
||||
|
||||
// MyContext 自定义 context
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:45 下午 2021/12/2
|
||||
type MyContext struct {
|
||||
Context
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// Package demo ...
|
||||
//
|
||||
// Description : demo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-12-02 12:46 下午
|
||||
package demo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestCancelCtx_UDC 测试自定义context
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:46 下午 2021/12/2
|
||||
func TestCancelCtx_UDC(t *testing.T) {
|
||||
childCancel := true
|
||||
|
||||
parentCtx, parentFunc := WithCancel(Background())
|
||||
mctx := MyContext{parentCtx}
|
||||
|
||||
childCtx, childFun := WithCancel(mctx)
|
||||
|
||||
if childCancel {
|
||||
childFun()
|
||||
} else {
|
||||
parentFunc()
|
||||
}
|
||||
|
||||
fmt.Println("parent context => ", parentCtx, reflect.TypeOf(parentCtx).String())
|
||||
fmt.Println("my context => ", mctx, reflect.TypeOf(mctx).String())
|
||||
fmt.Println("child context => ", childCtx, reflect.TypeOf(childCtx).String())
|
||||
|
||||
// 防止主协程退出太快,子协程来不及打印
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// Package easylock ...
|
||||
// Package easylock...
|
||||
//
|
||||
// Description : easylock ...
|
||||
// Description : easylock...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
|
@ -11,7 +11,7 @@ type option struct {
|
||||
flag string // 锁的标识
|
||||
}
|
||||
|
||||
// OptionFunc 设置option选项
|
||||
// Option 设置option选项
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Package easylock ...
|
||||
// Package easylock...
|
||||
//
|
||||
// Description : easylock ...
|
||||
// Description : easylock...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Package easylock ...
|
||||
// Package easylock...
|
||||
//
|
||||
// Description : 包装各种姿势的锁
|
||||
//
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Package easylock ...
|
||||
// Package easylock...
|
||||
//
|
||||
// Description : 分段的锁
|
||||
//
|
||||
|
@ -1,82 +0,0 @@
|
||||
// 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)
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// Package excel...
|
||||
//
|
||||
// Description : excel...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-19 2:05 下午
|
||||
package excel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCreate_GenerateSheet ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:05 下午 2021/11/19
|
||||
func TestCreate_GenerateSheet(t *testing.T) {
|
||||
e := NewExcel()
|
||||
sheetList := []SheetData{
|
||||
{true, "sheet11111", [][]interface{}{[]interface{}{123, 345, 678}}},
|
||||
{false, "sheet2222", [][]interface{}{[]interface{}{123, 345, 678}}},
|
||||
{false, "sheet3333", [][]interface{}{[]interface{}{123, 345, 678}}},
|
||||
{false, "sheet44444", [][]interface{}{[]interface{}{123, 345, 678}}},
|
||||
}
|
||||
fmt.Println(e.GenerateSheet(sheetList))
|
||||
fmt.Println(e.Save("./test.xlsx"))
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// 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
174
excel/read.go
@ -1,174 +0,0 @@
|
||||
// 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,54 +0,0 @@
|
||||
// Package excel...
|
||||
//
|
||||
// Description : excel...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-19 4:12 下午
|
||||
package excel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestRead_GetAllData ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:12 下午 2021/11/19
|
||||
func TestRead_GetAllData(t *testing.T) {
|
||||
r, _ := NewRead("./test.xlsx", "")
|
||||
fmt.Println(r.GetAllData())
|
||||
}
|
||||
|
||||
// TestRead_GetAllDataToMap ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:12 下午 2021/11/19
|
||||
func TestRead_GetAllDataToMap(t *testing.T) {
|
||||
r, _ := NewRead("./test.xlsx", "")
|
||||
fmt.Println(r.GetAllDataToMap([]string{"num1", "num2", "num3", "num4", "num5"}))
|
||||
fmt.Println(r.GetAllDataToMap([]string{"num1", "num2"}))
|
||||
}
|
||||
|
||||
// TestRead_ExtractAssignCol ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:12 下午 2021/11/19
|
||||
func TestRead_ExtractAssignCol(t *testing.T) {
|
||||
r, _ := NewRead("./test.xlsx", "")
|
||||
fmt.Println(r.ExtractAssignCol([]int{0, 2, 8}))
|
||||
}
|
||||
|
||||
// TestRead_ExtractAssignColToMap ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:12 下午 2021/11/19
|
||||
func TestRead_ExtractAssignColToMap(t *testing.T) {
|
||||
r, _ := NewRead("./test.xlsx", "")
|
||||
fmt.Println(r.ExtractAssignColToMap(map[int]string{0: "num1", 2: "num3", 10: "num11"}))
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Package api ...
|
||||
// Package gin ...
|
||||
//
|
||||
// Description : 便捷的相关API处理
|
||||
//
|
||||
@ -23,7 +23,7 @@ type IApi interface {
|
||||
GetURI() string
|
||||
// GetMiddleWareList 使用的中间件列表
|
||||
GetMiddleWareList() []gin.HandlerFunc
|
||||
// GetHandler 处理的handler
|
||||
// 处理的handler
|
||||
GetHandler() gin.HandlerFunc
|
||||
}
|
||||
|
||||
|
@ -19,36 +19,12 @@ import (
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:53 下午 2021/3/9
|
||||
func InitRequest(startTimeField string, traceIDField string) gin.HandlerFunc {
|
||||
func InitRequest() func(ctx *gin.Context) {
|
||||
return func(ctx *gin.Context) {
|
||||
// 设置请求开始时间
|
||||
if len(startTimeField) == 0 {
|
||||
startTimeField = "start_time"
|
||||
}
|
||||
if len(traceIDField) == 0 {
|
||||
traceIDField = "trace_id"
|
||||
}
|
||||
ctx.Set(startTimeField, time.Now().UnixMilli())
|
||||
ctx.Set("start_time", time.Now().Unix())
|
||||
// 设置请求trace_id
|
||||
ctx.Set(traceIDField, commonUtil.GetHostIP()+"-"+ctx.ClientIP()+"-"+time.Now().Format("20060102150405")+"-"+commonUtil.Md5(commonUtil.GenRandomString("", 16)))
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// SupportCross 支持跨域
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 9:40 PM 2022/1/13
|
||||
func SupportCross(header map[string]string) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
ctx.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token, Admin-User-Token, admin-user-token")
|
||||
ctx.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") //服务器支持的所有跨域请求的方
|
||||
ctx.Header("Access-Control-Expose-Headers", "admin-user-token, Admin-User-Token, Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||||
for key, val := range header {
|
||||
ctx.Header(key, val)
|
||||
}
|
||||
ctx.Set("trace_id", time.Now().Format("20060102150405")+"+"+commonUtil.GetHostIP()+"-"+commonUtil.Md5(commonUtil.GenRandomString("", 16)))
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
// Package static ...
|
||||
//
|
||||
// Description : static
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021/12/24 2:18 PM
|
||||
package static
|
||||
|
||||
// MapRule 定义映射规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:18 PM 2021/12/24
|
||||
type MapRule struct {
|
||||
URIPrefix string `json:"uri_prefix"` // 路由前缀
|
||||
StaticDirPath string `json:"static_dir_path"` // 静态资源路由
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Package static ...
|
||||
//
|
||||
// Description : 启动静态资源服务器
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021/12/24 2:14 PM
|
||||
package static
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register 静态资源服务器
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:17 PM 2021/12/24
|
||||
func Register(router *gin.Engine, ruleList []*MapRule) {
|
||||
for _, rule := range ruleList {
|
||||
router.StaticFS(rule.URIPrefix, http.Dir(rule.StaticDirPath))
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ func Response(ctx *gin.Context, code interface{}, message string, data interface
|
||||
"message": message,
|
||||
"data": data,
|
||||
"trace_id": ctx.GetString("trace_id"),
|
||||
"cost": time.Now().UnixMilli() - ctx.GetInt64("start_time"),
|
||||
"cost": time.Since(time.Unix(ctx.GetInt64("start_time"), 0)).Seconds(),
|
||||
}
|
||||
ctx.JSON(http.StatusOK, responseData)
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
// 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
|
@ -1,165 +0,0 @@
|
||||
// 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"`
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// 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
|
||||
}
|
113
go.mod
113
go.mod
@ -2,113 +2,72 @@ module git.zhangdeman.cn/zhangdeman/gopkg
|
||||
|
||||
go 1.17
|
||||
|
||||
replace github.com/coreos/bbolt v1.3.4 => go.etcd.io/bbolt v1.3.4
|
||||
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
|
||||
|
||||
require (
|
||||
github.com/Shopify/sarama v1.21.0
|
||||
github.com/apolloconfig/agollo/v4 v4.0.9
|
||||
github.com/coreos/etcd v3.3.27+incompatible
|
||||
github.com/Shopify/sarama v1.29.1
|
||||
github.com/ddliu/go-httpclient v0.6.9
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-redis/redis/v8 v8.11.4
|
||||
github.com/go-redis/redis_rate/v9 v9.1.2
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/go-redis/redis/v8 v8.11.3
|
||||
github.com/go-redis/redis_rate/v9 v9.1.1
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/gjson v1.11.0
|
||||
github.com/xuri/excelize/v2 v2.4.1
|
||||
github.com/tidwall/gjson v1.9.0
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
||||
go.etcd.io/etcd v3.3.27+incompatible
|
||||
go.uber.org/zap v1.20.0
|
||||
go.uber.org/zap v1.19.1
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gorm.io/driver/mysql v1.2.0
|
||||
gorm.io/gorm v1.22.4
|
||||
gorm.io/driver/mysql v1.1.2
|
||||
gorm.io/gorm v1.21.15
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/DataDog/zstd v1.3.5 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/coreos/bbolt v1.3.4 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/eapache/go-resiliency v1.2.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/frankban/quicktest v1.14.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.10.1 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.0-20210608040537-544b4180ac70 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.0.0 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.4 // indirect
|
||||
github.com/jinzhu/now v1.1.2 // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/klauspost/compress v1.12.2 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/lestrrat-go/strftime v1.0.5 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // 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/pierrec/lz4 v2.6.0+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.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/soheilhy/cmux v0.1.5 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.8.1 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // 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/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
|
||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
||||
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
|
||||
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b // indirect
|
||||
golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect
|
||||
google.golang.org/grpc v1.40.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // 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
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.64.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
760
go.sum
760
go.sum
@ -1,851 +1,271 @@
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/zstd v1.3.5 h1:DtpNbljikUepEPD16hD4LvIcmhnhdLTiW/5pHgbmp14=
|
||||
github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Shopify/sarama v1.21.0 h1:0GKs+e8mn1RRUzfg9oUXv3v7ZieQLmOZF/bfnmmGhM8=
|
||||
github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ=
|
||||
github.com/Shopify/sarama v1.29.1 h1:wBAacXbYVLmWieEA/0X/JagDdCZ8NVFOfS6l6+2u5S0=
|
||||
github.com/Shopify/sarama v1.29.1/go.mod h1:mdtqvCSg8JOxk8PmpTNGyo6wzd4BMm4QXSfDnTXmgkE=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apolloconfig/agollo/v4 v4.0.9 h1:4YzFSOVTZjGU2ag0XxL0y311TAkEsqh9a5pBS8FOgaI=
|
||||
github.com/apolloconfig/agollo/v4 v4.0.9/go.mod h1:n/7qxpKOTbegygLmO5OKmFWCdy3T+S/zioBGlo457Dk=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA=
|
||||
github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ddliu/go-httpclient v0.6.9 h1:/3hsBVpcgCJwqm1dkVlnAJ9NWuYInbRc+i9FyUXX/LE=
|
||||
github.com/ddliu/go-httpclient v0.6.9/go.mod h1:zM9P0OxV4OGGz1pt/ibuj0ooX2SWH9a6MvXZLbT0JMc=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
|
||||
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
|
||||
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig=
|
||||
github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
|
||||
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
|
||||
github.com/go-redis/redis_rate/v9 v9.1.2 h1:H0l5VzoAtOE6ydd38j8MCq3ABlGLnvvbA1xDSVVCHgQ=
|
||||
github.com/go-redis/redis_rate/v9 v9.1.2/go.mod h1:oam2de2apSgRG8aJzwJddXbNu91Iyz1m8IKJE2vpvlQ=
|
||||
github.com/go-redis/redis/v8 v8.3.4/go.mod h1:jszGxBCez8QA1HWSmQxJO9Y82kNibbUmeYhKWrBejTU=
|
||||
github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8=
|
||||
github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc=
|
||||
github.com/go-redis/redis_rate/v9 v9.1.1 h1:7SIrbnhQ7zsTNEgIvprFhJf7/+l3wSpZc2iRVwUmaq8=
|
||||
github.com/go-redis/redis_rate/v9 v9.1.1/go.mod h1:jjU9YxOSZ3cz0yj1QJVAJiy5ueKmL9o4AySJHcKyTSE=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20210608040537-544b4180ac70 h1:QvkCapbHb5N1sQMkoQkCLOcBmss196N/m2F64fCA7mY=
|
||||
github.com/golang/snappy v0.0.0-20210608040537-544b4180ac70/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
|
||||
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
|
||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
|
||||
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
|
||||
github.com/lestrrat-go/strftime v1.0.5 h1:A7H3tT8DhTz8u65w+JRpiBxM4dINQhUXAZnhBa2xeOE=
|
||||
github.com/lestrrat-go/strftime v1.0.5/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/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/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
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=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
|
||||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU=
|
||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A=
|
||||
github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU=
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
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=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0=
|
||||
github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k=
|
||||
github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4=
|
||||
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/gjson v1.9.0 h1:+Od7AE26jAaMgVC31cQV/Ope5iKXulNMflrlB7k+F9E=
|
||||
github.com/tidwall/gjson v1.9.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
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/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
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/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/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.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/etcd v3.3.27+incompatible h1:5hMrpf6REqTHV2LW2OclNpRtxI0k9ZplMemJsMSWju0=
|
||||
go.etcd.io/etcd v3.3.27+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.20.0 h1:N4oPlghZwYG55MlU6LXk/Zp00FVNE9X9wrYO8CEs4lc=
|
||||
go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
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-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
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/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
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-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-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0=
|
||||
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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-20210603081109-ebe580a85c40/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb h1:PVGECzEo9Y3uOidtkHGdd347NjLtITfJFO9BxFpmRoo=
|
||||
golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.64.0 h1:Mj2zXEXcNb5joEiSA0zc3HZpTst/iyjNiR4CN8tDzOg=
|
||||
gopkg.in/ini.v1 v1.64.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
@ -853,20 +273,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.2.0 h1:l8+9VwjjyzEkw0PNPBOr2JHhLOGVk7XEnl5hk42bcvs=
|
||||
gorm.io/driver/mysql v1.2.0/go.mod h1:4RQmTg4okPghdt+kbe6e1bTXIQp7Ny1NnBn/3Z6ghjk=
|
||||
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gorm.io/gorm v1.22.4 h1:8aPcyEJhY0MAt8aY6Dc524Pn+pO29K+ydu+e/cXSpQM=
|
||||
gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M=
|
||||
gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM=
|
||||
gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk=
|
||||
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
|
@ -20,37 +20,26 @@ import (
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
)
|
||||
|
||||
// MapDataRule 数据映射结果
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:09 PM 2022/1/17
|
||||
type MapDataRule struct {
|
||||
MapKey string
|
||||
DefaultValue string
|
||||
IsComplexType bool
|
||||
}
|
||||
|
||||
// NewFilter 获取解析的实例
|
||||
// NewParseJSONTree 获取解析的实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:43 下午 2021/3/14
|
||||
func NewFilter(data interface{}, rule map[string]MapDataRule) *Filter {
|
||||
func NewFilter(data interface{}, rule map[string]string) *Filter {
|
||||
return &Filter{
|
||||
data: data,
|
||||
rule: rule,
|
||||
}
|
||||
}
|
||||
|
||||
// Filter 解析json树
|
||||
// ParseJSONTree 解析json树
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:41 下午 2021/3/14
|
||||
type Filter struct {
|
||||
data interface{}
|
||||
rule map[string]MapDataRule
|
||||
rule map[string]string
|
||||
}
|
||||
|
||||
// Result 数据过滤结果
|
||||
@ -65,12 +54,12 @@ func (f *Filter) Result() (*DynamicJSON, error) {
|
||||
result := NewDynamicJSON()
|
||||
byteData, _ := json.Marshal(f.data)
|
||||
source := string(byteData)
|
||||
for extraDataPath, newDataRule := range f.rule {
|
||||
for extraDataPath, newDataPath := range f.rule {
|
||||
// 为数组的处理
|
||||
pathArr := strings.Split(extraDataPath, ".[].")
|
||||
val := gjson.Get(source, pathArr[0])
|
||||
if len(pathArr) == 1 {
|
||||
f.SetValue(result, newDataRule.MapKey, val.Value(), false, 0)
|
||||
f.SetValue(result, newDataPath, val.Value(), false, 0)
|
||||
continue
|
||||
}
|
||||
// 支持list再抽取一层,处于性能考虑,这么限制,不做递归无限深度处理
|
||||
@ -80,11 +69,9 @@ func (f *Filter) Result() (*DynamicJSON, error) {
|
||||
data := item.Map()
|
||||
for _, key := range ketList {
|
||||
if v, exist := data[key]; exist {
|
||||
result.SetValue(strings.ReplaceAll(newDataRule.MapKey, "[]", fmt.Sprintf("[%d]", idx)), data[key].Value(), v.IsObject() || v.IsArray())
|
||||
} else {
|
||||
// 结果集中不存在对应key,设置默认值
|
||||
result.SetValue(strings.ReplaceAll(newDataRule.MapKey, "[]", fmt.Sprintf("[%d]", idx)), newDataRule.DefaultValue, newDataRule.IsComplexType)
|
||||
result.SetValue(strings.ReplaceAll(newDataPath, "[]", fmt.Sprintf("[%d]", idx)), data[key].Raw, v.IsObject() || v.IsArray())
|
||||
}
|
||||
// 结果集中不存在对应key,丢弃
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,175 +0,0 @@
|
||||
// Package json_tool...
|
||||
//
|
||||
// Description : json_tool...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-03-10 11:44 下午
|
||||
package json_tool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestJSON ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:58 下午 2021/3/14
|
||||
func TestJSON(t *testing.T) {
|
||||
tree := NewDynamicJSON()
|
||||
fmt.Println(tree.extraSliceIndex("[200]"))
|
||||
tree.SetValue("extra.height.value", 180, false)
|
||||
tree.SetValue("extra.height.unit.use", "cm", false)
|
||||
tree.SetValue("extra.height.unit.open", "1", false)
|
||||
tree.SetValue("name", "zhangdeman", false)
|
||||
tree.SetValue("good.name", "good", false)
|
||||
tree.SetValue("work", "111", false)
|
||||
tree.SetValue("good.price", "180", false)
|
||||
tree.SetValue("good.unit", "$", false)
|
||||
tree.SetValue("slice.[0].name", "zhang", false)
|
||||
tree.SetValue("slice.[0].age", 30, false)
|
||||
tree.SetValue("slice.[1].name", "de", false)
|
||||
tree.SetValue("slice.[2].name", "man", false)
|
||||
tree.SetValue("slice.[3]", "zhangdeman", false)
|
||||
fmt.Println(tree.String())
|
||||
tree = NewDynamicJSON()
|
||||
tree.SetValue("[0]", "zhang", false)
|
||||
tree.SetValue("[1]", "de", false)
|
||||
tree.SetValue("[2]", "man", false)
|
||||
fmt.Println(tree.String())
|
||||
}
|
||||
|
||||
// TestType 判断数据类型断言
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:59 下午 2021/3/14
|
||||
func TestType(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestSelect 测试动态选择字段
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 9:47 下午 2021/4/13
|
||||
func TestSelect(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
},
|
||||
"slice": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "b": 2, "c": 4},
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
{"name": "bob", "age": 28, "number": 2, "list": []int{1, 2, 3}},
|
||||
},
|
||||
}
|
||||
rule := map[string]MapDataRule{
|
||||
"name": {
|
||||
MapKey: "user_name",
|
||||
DefaultValue: "用户姓名默认值",
|
||||
IsComplexType: false,
|
||||
},
|
||||
"extra.age": {MapKey: "user_age", DefaultValue: "用户年龄默认值", IsComplexType: false},
|
||||
"extra.height": {MapKey: "user_height", DefaultValue: "扩展高度默认值", IsComplexType: false},
|
||||
"table.[].name": {MapKey: "slice.[].name_modify", DefaultValue: "列表姓名默认值", IsComplexType: false},
|
||||
"table.[].list": {MapKey: "slice.[].data_list", DefaultValue: "[\"567\",\"678\",\"789\"]", IsComplexType: true},
|
||||
}
|
||||
filter := NewFilter(source, rule)
|
||||
d, e := filter.Result()
|
||||
if nil != e {
|
||||
fmt.Println(e)
|
||||
return
|
||||
}
|
||||
fmt.Println(d.String())
|
||||
}
|
||||
|
||||
// TestParse 测试获取JSON数据结构
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:59 PM 2022/1/9
|
||||
func TestParse(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
"obj": map[string]interface{}{
|
||||
"la": "aaaa",
|
||||
},
|
||||
},
|
||||
"slice": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "b": 2, "c": 4},
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1, "obj": map[string]interface{}{"enen": "en"}},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
},
|
||||
"two_slice": []map[string]interface{}{
|
||||
{
|
||||
"students": []map[string]interface{}{
|
||||
{
|
||||
"name": "enen",
|
||||
"age": 18,
|
||||
"score": []float64{1, 2, 3, 45},
|
||||
},
|
||||
},
|
||||
"other": []interface{}{"others"},
|
||||
"read_only": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
fmt.Println(GetJSONDataStruct(string(byteData)))
|
||||
}
|
||||
|
||||
// TestParseWithType 测试获取JSON数据结构
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:59 PM 2022/1/9
|
||||
func TestParseWithType(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
"obj": map[string]interface{}{
|
||||
"la": "aaaa",
|
||||
},
|
||||
},
|
||||
"slice": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "d": 5.5, "e": "qqq"},
|
||||
"empty_obj": map[string]interface{}{},
|
||||
"empty_list": make([]interface{}, 0),
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1, "obj": map[string]interface{}{"enen": "en"}},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
},
|
||||
"two_slice": []map[string]interface{}{
|
||||
{
|
||||
"students": []map[string]interface{}{
|
||||
{
|
||||
"name": "enen",
|
||||
"age": 18,
|
||||
"score": []float64{1, 2, 3, 45},
|
||||
},
|
||||
},
|
||||
"other": []interface{}{"others"},
|
||||
"read_only": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
fmt.Println(GetJSONDataStructWithType(string(byteData)))
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
// Package json_tool ...
|
||||
//
|
||||
// Description : json_tool ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022-01-09 10:48 PM
|
||||
package json_tool
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// Field ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022/1/10 10:47 PM
|
||||
type Field struct {
|
||||
Path string `json:"path"` // 路径
|
||||
Type string `json:"type"` // 类型
|
||||
Example string `json:"example"` // 示例值
|
||||
}
|
||||
|
||||
const (
|
||||
// FieldTypeInt ...
|
||||
FieldTypeInt = "int64"
|
||||
// FieldTypeIntSlice ...
|
||||
FieldTypeIntSlice = "[]int64"
|
||||
// FieldTypeFloat ...
|
||||
FieldTypeFloat = "float64"
|
||||
// FieldTypeFloatSlice ...
|
||||
FieldTypeFloatSlice = "[]float64"
|
||||
// FieldTypeBool ...
|
||||
FieldTypeBool = "bool"
|
||||
// FieldTypeBoolSlice ...
|
||||
FieldTypeBoolSlice = "[]bool"
|
||||
// FieldTypeString ...
|
||||
FieldTypeString = "string"
|
||||
// FieldTypeStringSLice ...
|
||||
FieldTypeStringSLice = "string"
|
||||
// FieldTypeAny ...
|
||||
FieldTypeAny = "interface{}"
|
||||
// FieldTypeAnySlice ...
|
||||
FieldTypeAnySlice = "[]interface{}"
|
||||
// FieldTypeSlice ...
|
||||
FieldTypeSlice = "[]interface{}"
|
||||
// FieldTypeMap ...
|
||||
FieldTypeMap = "map"
|
||||
// FieldTypeMapSlice ...
|
||||
FieldTypeMapSlice = "[]map"
|
||||
)
|
||||
|
||||
// GetJSONDataStruct 获取JSON数据的结构
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:53 PM 2022/1/9
|
||||
func GetJSONDataStruct(data string) ([]string, error) {
|
||||
if !gjson.Valid(data) {
|
||||
return make([]string, 0), errors.New("JSON format is invalid")
|
||||
}
|
||||
pathList := make([]string, 0)
|
||||
r := gjson.Parse(data)
|
||||
r.ForEach(func(key, value gjson.Result) bool {
|
||||
if value.Value() == nil {
|
||||
pathList = append(pathList, key.String())
|
||||
return true
|
||||
}
|
||||
if value.IsObject() {
|
||||
if value.String() == "{}" {
|
||||
pathList = append(pathList, key.String())
|
||||
} else {
|
||||
list, _ := GetJSONDataStruct(value.String())
|
||||
for _, k := range list {
|
||||
pathList = append(pathList, key.String()+"."+k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsArray() {
|
||||
dataList := value.Array()
|
||||
if len(dataList) > 0 {
|
||||
if !dataList[0].IsObject() && !dataList[0].IsArray() {
|
||||
pathList = append(pathList, key.String())
|
||||
} else {
|
||||
list, _ := GetJSONDataStruct(dataList[0].String())
|
||||
for _, k := range list {
|
||||
pathList = append(pathList, key.String()+".[]."+k)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pathList = append(pathList, key.String())
|
||||
}
|
||||
}
|
||||
|
||||
if !value.IsObject() && !value.IsArray() {
|
||||
pathList = append(pathList, key.String())
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
return pathList, nil
|
||||
}
|
||||
|
||||
// GetJSONDataStructWithType 获取数据结构,并获取类型
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022/1/10 10:47 PM
|
||||
func GetJSONDataStructWithType(data string) ([]Field, error) {
|
||||
if !gjson.Valid(data) {
|
||||
return make([]Field, 0), errors.New("JSON format is invalid")
|
||||
}
|
||||
pathList := make([]Field, 0)
|
||||
r := gjson.Parse(data)
|
||||
r.ForEach(func(key, value gjson.Result) bool {
|
||||
if value.Value() == nil {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String(),
|
||||
Type: FieldTypeAny,
|
||||
Example: "nil",
|
||||
})
|
||||
return true
|
||||
}
|
||||
if value.IsObject() {
|
||||
if value.String() == "{}" {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String(),
|
||||
Type: FieldTypeMap,
|
||||
Example: "{}",
|
||||
})
|
||||
} else {
|
||||
list, _ := GetJSONDataStructWithType(value.String())
|
||||
for _, field := range list {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String() + "." + field.Path,
|
||||
Type: field.Type,
|
||||
Example: field.Example,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsArray() {
|
||||
dataList := value.Array()
|
||||
if len(dataList) > 0 {
|
||||
if !dataList[0].IsObject() && !dataList[0].IsArray() {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String(),
|
||||
Type: "[]" + GetDataType(dataList[0]),
|
||||
Example: value.String(),
|
||||
})
|
||||
} else {
|
||||
list, _ := GetJSONDataStructWithType(dataList[0].String())
|
||||
for _, field := range list {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String() + ".[]." + field.Path,
|
||||
Type: field.Type,
|
||||
Example: field.Example,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String(),
|
||||
Type: FieldTypeSlice,
|
||||
Example: "[]",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !value.IsObject() && !value.IsArray() {
|
||||
pathList = append(pathList, Field{
|
||||
Path: key.String(),
|
||||
Type: GetDataType(value),
|
||||
Example: value.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
return pathList, nil
|
||||
}
|
||||
|
||||
// GetDataType 获取数据类型
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022/1/10 11:00 PM
|
||||
func GetDataType(value gjson.Result) string {
|
||||
switch value.Type.String() {
|
||||
default:
|
||||
return FieldTypeAny
|
||||
case "Null":
|
||||
return FieldTypeAny
|
||||
case "False":
|
||||
return FieldTypeBool
|
||||
case "True":
|
||||
return FieldTypeBool
|
||||
case "Number":
|
||||
if strings.Contains(value.String(), ".") {
|
||||
return FieldTypeFloat
|
||||
}
|
||||
return FieldTypeInt
|
||||
case "String":
|
||||
return FieldTypeString
|
||||
case "JSON":
|
||||
if strings.HasPrefix(strings.TrimSpace(value.String()), "[") {
|
||||
return FieldTypeSlice
|
||||
}
|
||||
return FieldTypeMap
|
||||
}
|
||||
}
|
@ -4,17 +4,14 @@
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021/03/01 9:52 下午
|
||||
// Date : 2021-03-01 9:52 下午
|
||||
package wrapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
@ -50,36 +47,15 @@ func NewGormV2(loggerLevel zapcore.Level, consoleOutput bool, encoder zapcore.En
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewGormLoggerWithInstance 获取gorm日志实现
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:36 PM 2021/12/24
|
||||
func NewGormLoggerWithInstance(ctx *gin.Context, dbClient *gorm.DB, instance *zap.Logger, node string, extraCtxFieldList []string) logger.Interface {
|
||||
return &Gorm{
|
||||
dbClient: dbClient,
|
||||
instance: instance,
|
||||
traceIDField: "",
|
||||
extraCtxFieldList: extraCtxFieldList,
|
||||
flag: "",
|
||||
node: node,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Gorm v2 版本库日志实现
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 9:55 下午 2021/3/1
|
||||
type Gorm struct {
|
||||
dbClient *gorm.DB
|
||||
instance *zap.Logger // 日志实例
|
||||
traceIDField string // 串联请求上下文的的ID
|
||||
extraCtxFieldList []string // 从请求上线问提取的字段
|
||||
flag string // 数据库标识
|
||||
node string // 数据库节点 master / slave
|
||||
ctx *gin.Context // gin上下文
|
||||
instance *zap.Logger // 日志实例
|
||||
traceIDField string // 串联请求上下文的的ID
|
||||
flag string // 数据库标识
|
||||
}
|
||||
|
||||
// LogMode ...
|
||||
@ -97,7 +73,12 @@ func (g *Gorm) LogMode(level logger.LogLevel) logger.Interface {
|
||||
//
|
||||
// Date : 10:18 下午 2021/3/1
|
||||
func (g *Gorm) Info(ctx context.Context, s string, i ...interface{}) {
|
||||
g.write(nil, "info")
|
||||
g.instance.Info(
|
||||
"Info日志",
|
||||
zap.String(g.traceIDField, g.getTraceID(ctx)),
|
||||
zap.String("db_flag", g.flag),
|
||||
zap.String("message", fmt.Sprintf(s, i...)),
|
||||
)
|
||||
}
|
||||
|
||||
// Warn ...
|
||||
@ -106,7 +87,12 @@ func (g *Gorm) Info(ctx context.Context, s string, i ...interface{}) {
|
||||
//
|
||||
// Date : 10:16 下午 2021/3/1
|
||||
func (g *Gorm) Warn(ctx context.Context, s string, i ...interface{}) {
|
||||
g.write(nil, "warn")
|
||||
g.instance.Warn(
|
||||
"SQL执行产生Warning",
|
||||
zap.String(g.traceIDField, g.getTraceID(ctx)),
|
||||
zap.String("db_flag", g.flag),
|
||||
zap.String("message", fmt.Sprintf(s, i...)),
|
||||
)
|
||||
}
|
||||
|
||||
// Error 日志
|
||||
@ -115,7 +101,12 @@ func (g *Gorm) Warn(ctx context.Context, s string, i ...interface{}) {
|
||||
//
|
||||
// Date : 10:18 下午 2021/3/1
|
||||
func (g *Gorm) Error(ctx context.Context, s string, i ...interface{}) {
|
||||
g.write(nil, "error")
|
||||
g.instance.Warn(
|
||||
"SQL执行产生Error",
|
||||
zap.String(g.traceIDField, g.getTraceID(ctx)),
|
||||
zap.String("db_flag", g.flag),
|
||||
zap.String("message", fmt.Sprintf(s, i...)),
|
||||
)
|
||||
}
|
||||
|
||||
// Trace Trace 记录
|
||||
@ -132,7 +123,8 @@ func (g *Gorm) Trace(ctx context.Context, begin time.Time, fc func() (string, in
|
||||
sql, affectRows = fc()
|
||||
}
|
||||
|
||||
dataList := []zap.Field{
|
||||
g.instance.Info(
|
||||
"SQL执行记录",
|
||||
zap.String(g.traceIDField, g.getTraceID(ctx)),
|
||||
zap.String("db_flag", g.flag),
|
||||
zap.Int64("begin_time", start),
|
||||
@ -141,45 +133,7 @@ func (g *Gorm) Trace(ctx context.Context, begin time.Time, fc func() (string, in
|
||||
zap.String("sql", sql),
|
||||
zap.Int64("affect_rows", affectRows),
|
||||
zap.Error(err),
|
||||
}
|
||||
g.write(dataList, "info")
|
||||
|
||||
}
|
||||
|
||||
// write ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:11 PM 2021/12/24
|
||||
func (g *Gorm) write(dataList []zap.Field, level string) {
|
||||
if nil == g.instance {
|
||||
// 未设置日志实例
|
||||
return
|
||||
}
|
||||
if nil == dataList {
|
||||
dataList = make([]zap.Field, 0)
|
||||
}
|
||||
if nil != g.ctx {
|
||||
for _, extraField := range g.extraCtxFieldList {
|
||||
dataList = append(dataList, zap.Any(extraField, g.ctx.Value(extraField)))
|
||||
}
|
||||
}
|
||||
|
||||
// 补齐 flag、node
|
||||
sql := g.dbClient.Dialector.Explain(g.dbClient.Statement.SQL.String(), g.dbClient.Statement.Vars...)
|
||||
affectRows := g.dbClient.RowsAffected
|
||||
dataList = append(dataList, zap.String("db_node", g.node), zap.String("db_flag", g.flag), zap.String("execute_sql", sql), zap.Int64("affect_rows", affectRows))
|
||||
message := "SQL执行记录"
|
||||
switch strings.ToLower(level) {
|
||||
case "info":
|
||||
g.instance.Info(message, dataList...)
|
||||
case "warn":
|
||||
g.instance.Warn(message, dataList...)
|
||||
case "error":
|
||||
g.instance.Error(message, dataList...)
|
||||
default:
|
||||
g.instance.Info(message, dataList...)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// getTraceID 获取traceID
|
||||
@ -191,7 +145,7 @@ func (g *Gorm) getTraceID(ctx context.Context) string {
|
||||
return fmt.Sprintf("%v", ctx.Value(g.traceIDField))
|
||||
}
|
||||
|
||||
// GetGormSQL 获取trace fn
|
||||
// GetGormSQL 获取tracefn
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
|
@ -1,28 +0,0 @@
|
||||
// Package apollo...
|
||||
//
|
||||
// Description : 扩展第三方库的一些函数
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 10:16 下午
|
||||
package apollo
|
||||
|
||||
import (
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GetValueWithReceiver 读取数据,并解析到指定的数据结构中
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:18 下午 2021/11/24
|
||||
func GetValueWithReceiver(key string, receiver interface{}) error {
|
||||
var (
|
||||
result string
|
||||
)
|
||||
if result = Client.GetStringValue(key, ""); len(result) == 0 {
|
||||
return errors.New("key is not found : " + key)
|
||||
}
|
||||
return util.JSONUnmarshalWithNumber([]byte(result), receiver)
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// Package apollo...
|
||||
//
|
||||
// Description : apollo...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 10:05 下午
|
||||
package apollo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/apolloconfig/agollo/v4"
|
||||
"github.com/apolloconfig/agollo/v4/env/config"
|
||||
)
|
||||
|
||||
var (
|
||||
// Client 客户端链接
|
||||
Client *agollo.Client
|
||||
)
|
||||
|
||||
// Init 初始化apollo客户端
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:12 下午 2021/11/24
|
||||
func Init(cfg *config.AppConfig) error {
|
||||
var err error
|
||||
|
||||
if Client, err = agollo.StartWithConfig(func() (*config.AppConfig, error) {
|
||||
return cfg, nil
|
||||
}); err != nil {
|
||||
return errors.New("apollo client init fail : " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
// Package apollo...
|
||||
//
|
||||
// Description : apollo...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 10:26 下午
|
||||
package apollo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/convert"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// OperateTypeIs 固定值
|
||||
OperateTypeIs = "is"
|
||||
// OperateTypeIn 在指定枚举值中
|
||||
OperateTypeIn = "in"
|
||||
// OperateTypeNotIn 不在指定枚举值中
|
||||
OperateTypeNotIn = "not_in"
|
||||
// OperateGt 大于
|
||||
OperateGt = "gt"
|
||||
// OperateGte 大于等于
|
||||
OperateGte = "gte"
|
||||
// OperateLt 小于
|
||||
OperateLt = "lt"
|
||||
// OperateLte 小于等于
|
||||
OperateLte = "lte"
|
||||
// OperateTypeContains 包含
|
||||
OperateTypeContains = "contains"
|
||||
// OperateTypeRegular 正则匹配
|
||||
OperateTypeRegular = "regular"
|
||||
)
|
||||
|
||||
var (
|
||||
// hasCompilerRegula 已编译正则,不进行重复编辑
|
||||
hasCompilerRegula map[string]*regexp.Regexp
|
||||
// regulaLock 编译正则用的锁
|
||||
regulaLock *sync.RWMutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
regulaLock = &sync.RWMutex{}
|
||||
hasCompilerRegula = make(map[string]*regexp.Regexp)
|
||||
}
|
||||
|
||||
// Rule 数据过滤规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:32 下午 2021/11/24
|
||||
type Rule struct {
|
||||
Name string `json:"name"` // 规则名称
|
||||
ConditionList []Condition `json:"condition_list"` // 条件列表
|
||||
Data map[string]interface{} `json:"data"` // 满足条件时返回的数据
|
||||
}
|
||||
|
||||
// Condition 条件处理
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:27 下午 2021/11/24
|
||||
type Condition struct {
|
||||
InputKey string `json:"input_key"` // 从输入数据中读取的key
|
||||
Operate string `json:"operate"` // 操作
|
||||
TargetValue string `json:"target_value"` // 目标值
|
||||
}
|
||||
|
||||
// Search 搜索key并按照指定条件过滤
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:01 下午 2021/11/24
|
||||
func Search(key string, inputData map[string]interface{}, receiver interface{}) error {
|
||||
if nil == receiver {
|
||||
return errors.New("receiver is nil")
|
||||
}
|
||||
if nil == inputData {
|
||||
inputData = make(map[string]interface{})
|
||||
}
|
||||
var (
|
||||
readResult string
|
||||
err error
|
||||
formatResult []Rule
|
||||
)
|
||||
if readResult = Client.GetStringValue(key, ""); len(readResult) == 0 {
|
||||
return errors.New("key is not found : " + key)
|
||||
}
|
||||
if err = json.Unmarshal([]byte(readResult), &formatResult); nil != err {
|
||||
return errors.New("parse read config fail : " + err.Error())
|
||||
}
|
||||
for _, rule := range formatResult {
|
||||
if checkRule(rule, inputData) {
|
||||
byteData, mErr := json.Marshal(rule.Data)
|
||||
if nil != mErr {
|
||||
return mErr
|
||||
}
|
||||
// 命中规则, 返回数据
|
||||
return util.JSONUnmarshalWithNumber(byteData, receiver)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkRule 检测数据是否命中规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:59 下午 2021/11/24
|
||||
func checkRule(rule Rule, inputData map[string]interface{}) bool {
|
||||
for _, cond := range rule.ConditionList {
|
||||
val, exist := inputData[cond.InputKey]
|
||||
if !exist {
|
||||
// 输入的key 不存在, 不符合规则
|
||||
return false
|
||||
}
|
||||
switch cond.Operate {
|
||||
case OperateTypeIs:
|
||||
if !is(val, cond.TargetValue) {
|
||||
return false
|
||||
}
|
||||
case OperateTypeIn:
|
||||
if !in(val, cond.TargetValue) {
|
||||
return false
|
||||
}
|
||||
case OperateTypeNotIn:
|
||||
if !notIn(val, cond.TargetValue) {
|
||||
return false
|
||||
}
|
||||
case OperateTypeContains:
|
||||
if !contains(val, cond.TargetValue) {
|
||||
return false
|
||||
}
|
||||
case OperateGt:
|
||||
if !compareNumber(val, cond.TargetValue, OperateGt) {
|
||||
return false
|
||||
}
|
||||
case OperateGte:
|
||||
if !compareNumber(val, cond.TargetValue, OperateGte) {
|
||||
return false
|
||||
}
|
||||
case OperateLt:
|
||||
if !compareNumber(val, cond.TargetValue, OperateLt) {
|
||||
return false
|
||||
}
|
||||
case OperateLte:
|
||||
if !compareNumber(val, cond.TargetValue, OperateLte) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// is 判断是否相等
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:28 上午 2021/11/25
|
||||
func is(inputVal interface{}, targetValue string) bool {
|
||||
return fmt.Sprintf("%v", inputVal) == targetValue
|
||||
}
|
||||
|
||||
// in ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:47 上午 2021/11/25
|
||||
func in(inputValue interface{}, targetValue string) bool {
|
||||
if nil == inputValue {
|
||||
return false
|
||||
}
|
||||
inputStr := fmt.Sprintf("%v", inputValue)
|
||||
targetList := strings.Split(targetValue, ",")
|
||||
for _, item := range targetList {
|
||||
if inputStr == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// notIn ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:47 上午 2021/11/25
|
||||
func notIn(inputValue interface{}, targetValue string) bool {
|
||||
if nil == inputValue {
|
||||
return false
|
||||
}
|
||||
inputStr := fmt.Sprintf("%v", inputValue)
|
||||
targetList := strings.Split(targetValue, ",")
|
||||
for _, item := range targetList {
|
||||
if inputStr == item {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// compareNumber ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:56 上午 2021/11/25
|
||||
func compareNumber(inputValue interface{}, targetValue string, operateType string) bool {
|
||||
if inputValue == nil || len(targetValue) == 0 {
|
||||
return false
|
||||
}
|
||||
var (
|
||||
err error
|
||||
inputFloat float64
|
||||
targetFloat float64
|
||||
)
|
||||
if err = convert.ConvertAssign(&inputFloat, inputValue); nil != err {
|
||||
return false
|
||||
}
|
||||
|
||||
if err = convert.ConvertAssign(&targetFloat, targetValue); nil != err {
|
||||
return false
|
||||
}
|
||||
switch operateType {
|
||||
case OperateGt:
|
||||
return inputFloat > targetFloat
|
||||
case OperateGte:
|
||||
return inputFloat >= targetFloat
|
||||
case OperateLt:
|
||||
return inputFloat < targetFloat
|
||||
case OperateLte:
|
||||
return inputFloat <= targetFloat
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// contains ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:03 下午 2021/11/25
|
||||
func contains(inputValue interface{}, targetValue string) bool {
|
||||
return strings.Contains(fmt.Sprintf("%v", inputValue), targetValue)
|
||||
}
|
||||
|
||||
// regula 正则匹配
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:15 下午 2021/11/25
|
||||
func regula(inputValue interface{}, targetValue string) bool {
|
||||
var (
|
||||
reg *regexp.Regexp
|
||||
err error
|
||||
)
|
||||
regulaLock.Lock()
|
||||
if _, exist := hasCompilerRegula[targetValue]; !exist {
|
||||
if reg, err = regexp.Compile(targetValue); nil != err {
|
||||
regulaLock.Unlock()
|
||||
return false
|
||||
}
|
||||
hasCompilerRegula[targetValue] = reg
|
||||
} else {
|
||||
reg = hasCompilerRegula[targetValue]
|
||||
}
|
||||
regulaLock.Unlock()
|
||||
|
||||
// 判断是否匹配到数据
|
||||
result := reg.FindAllStringSubmatch(fmt.Sprintf("%v", inputValue), -1)
|
||||
return len(result) > 0
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 11:25 上午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// 初始化client各种默认配置
|
||||
const (
|
||||
// DefaultDialTimeout 默认超时时间
|
||||
DefaultDialTimeout = 5 * time.Second
|
||||
// DefaultDialKeepAliveTime 默认ping时间
|
||||
DefaultDialKeepAliveTime = 3 * time.Second
|
||||
// DefaultDialKeepAliveTimeout ping之后等待响应的超时时间, 超时未响应, 连接将会断开
|
||||
DefaultDialKeepAliveTimeout = 5 * time.Second
|
||||
// DefaultMaxCallSendMsgSize 客户端请求体最大字节数, 默认 2M , 和etcd默认值保持一致
|
||||
DefaultMaxCallSendMsgSize = 2 * 1024 * 1024
|
||||
// DefaultMaxCallRecvMsgSize 客户端接受的响应题最大大小, 默认int32最大值, 和etcd默认值保持一致
|
||||
DefaultMaxCallRecvMsgSize = math.MaxInt32
|
||||
)
|
||||
|
||||
// 操作过程中各种默认配置
|
||||
const (
|
||||
// DefaultPutTimeout put 默认超时时间
|
||||
DefaultPutTimeout = time.Second
|
||||
// DefaultGetTimeout get 默认超时时间
|
||||
DefaultGetTimeout = time.Second
|
||||
// DefaultDeleteTimeout 删除的超时时间
|
||||
DefaultDeleteTimeout = time.Second
|
||||
)
|
||||
|
||||
// WatcherHandler 监听key变化的处理函数
|
||||
type WatcherHandler func(event *clientv3.Event)
|
||||
|
||||
// CancelWatcherHandler 取消监听后的处理函数
|
||||
type CancelWatcherHandler func(key string, data interface{})
|
||||
|
||||
// TimeoutWatcherHandler 超时之后的回调函数
|
||||
type TimeoutWatcherHandler func(key string, timeout time.Duration)
|
||||
|
||||
// LeaseKeepALiveHandler 续期成功的处理
|
||||
type LeaseKeepALiveHandler func(data *LeaseKeepAliveData)
|
||||
|
||||
// LeaseKeepAliveData 自动续期的数据结构
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 8:28 下午 2021/11/23
|
||||
type LeaseKeepAliveData struct {
|
||||
Key string `json:"key"` // 续期key
|
||||
StartTime int64 `json:"start_time"` // 开始续期时间
|
||||
LastLeaseTime int64 `json:"last_lease_time"` // 上一次续期事件时间
|
||||
LeaseCnt int64 `json:"lease_cnt"` // 续期次数
|
||||
HasFinish bool `json:"has_finish"` // 是否完成
|
||||
LeaseFinishType string `json:"lease_finish_type"` // 续期完成类型
|
||||
LeaseFinishTime int64 `json:"lease_finish_time"` // 续期完成时间
|
||||
LeaseDetail *clientv3.LeaseKeepAliveResponse `json:"lease_detail"` // 续约数据
|
||||
Data map[string]interface{} `json:"data"` // 携带的数据
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : 删除相关操作
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 12:42 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// DeleteWithOption ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:02 下午 2021/11/24
|
||||
func DeleteWithOption(ctx context.Context, key string, timeout time.Duration, optionList ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
if timeout <= 0 {
|
||||
timeout = DefaultDeleteTimeout
|
||||
}
|
||||
|
||||
var (
|
||||
cancelFunc context.CancelFunc
|
||||
deleteResponse *clientv3.DeleteResponse
|
||||
err error
|
||||
)
|
||||
ctx, cancelFunc = context.WithTimeout(ctx, timeout)
|
||||
defer cancelFunc()
|
||||
|
||||
if deleteResponse, err = Client.Delete(ctx, key, optionList...); nil != err {
|
||||
return nil, errors.New("delete key fail : " + err.Error())
|
||||
}
|
||||
|
||||
return deleteResponse, nil
|
||||
}
|
||||
|
||||
// DeleteWithKeyPrefix 基于 key 前缀, 删除key
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:12 下午 2021/11/24
|
||||
func DeleteWithKeyPrefix(ctx context.Context, keyPrefix string, timeout time.Duration) (*clientv3.DeleteResponse, error) {
|
||||
return DeleteWithOption(ctx, keyPrefix, timeout, clientv3.WithPrefix())
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 2:11 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestDeleteWithKeyPrefix ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:11 下午 2021/11/24
|
||||
func TestDeleteWithKeyPrefix(t *testing.T) {
|
||||
fmt.Println(DeleteWithKeyPrefix(nil, "/test", 0))
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// Package etcd ...
|
||||
//
|
||||
// Description : etcd ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 10:53 上午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
var (
|
||||
// Client 客户端
|
||||
Client *clientv3.Client
|
||||
)
|
||||
|
||||
// InitEtcdClient 初始化etcd连接
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:53 上午 2021/11/23
|
||||
func InitEtcdClient(cfg clientv3.Config) error {
|
||||
if nil == cfg.Endpoints || len(cfg.Endpoints) == 0 {
|
||||
return errors.New("endpoints is empty")
|
||||
}
|
||||
|
||||
// 连接超时
|
||||
if cfg.DialTimeout == 0 {
|
||||
cfg.DialTimeout = DefaultDialTimeout
|
||||
}
|
||||
|
||||
// ping 时间间隔
|
||||
if cfg.DialKeepAliveTime == 0 {
|
||||
cfg.DialKeepAliveTime = DefaultDialKeepAliveTime
|
||||
}
|
||||
|
||||
// ping 响应超时时间
|
||||
if cfg.DialKeepAliveTimeout == 0 {
|
||||
cfg.DialKeepAliveTimeout = DefaultDialKeepAliveTimeout
|
||||
}
|
||||
|
||||
// 客户端发送的最大请求体大小
|
||||
if cfg.MaxCallSendMsgSize <= 0 {
|
||||
cfg.MaxCallSendMsgSize = DefaultMaxCallSendMsgSize
|
||||
}
|
||||
|
||||
// 客户端接受的最大响应体大小
|
||||
if cfg.MaxCallRecvMsgSize <= 0 {
|
||||
cfg.MaxCallRecvMsgSize = DefaultMaxCallRecvMsgSize
|
||||
}
|
||||
var err error
|
||||
if Client, err = clientv3.New(cfg); nil != err {
|
||||
return errors.New("etcd连接失败 : " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
// Package etcd ...
|
||||
//
|
||||
// Description : 租约相关操作
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 6:03 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// LeaseOnce 申请一个一次性租约
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:06 下午 2021/11/23
|
||||
func LeaseOnce(ctx context.Context, key string, val string, ttl int64) error {
|
||||
if ttl <= 0 {
|
||||
return errors.New("lease time must be more than 0")
|
||||
}
|
||||
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
var (
|
||||
resp *clientv3.LeaseGrantResponse
|
||||
err error
|
||||
cancelFunc context.CancelFunc
|
||||
)
|
||||
ctx, cancelFunc = context.WithCancel(ctx)
|
||||
defer cancelFunc()
|
||||
// 创建一个5秒的租约
|
||||
if resp, err = Client.Grant(ctx, ttl); err != nil {
|
||||
return errors.New("lease grant error : " + err.Error())
|
||||
}
|
||||
|
||||
// ttl 秒钟之后, 这个key就会被移除
|
||||
if _, err = Client.Put(ctx, key, val, clientv3.WithLease(resp.ID)); err != nil {
|
||||
return errors.New("lease key put fail : " + err.Error())
|
||||
}
|
||||
_, err = Client.KeepAliveOnce(ctx, resp.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// LeaseKeepAliveForever 无限续租一个key
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:40 下午 2021/11/23
|
||||
func LeaseKeepAliveForever(ctx context.Context, key string, val string, ttl int64, keepAliveHandler LeaseKeepALiveHandler) error {
|
||||
if ttl <= 0 {
|
||||
return errors.New("lease time must be more than 0")
|
||||
}
|
||||
if nil == ctx {
|
||||
ctx = context.TODO()
|
||||
}
|
||||
var (
|
||||
resp *clientv3.LeaseGrantResponse
|
||||
respChan <-chan *clientv3.LeaseKeepAliveResponse
|
||||
err error
|
||||
)
|
||||
// 创建一个5秒的租约
|
||||
if resp, err = Client.Grant(ctx, ttl); err != nil {
|
||||
return errors.New("lease grant error : " + err.Error())
|
||||
}
|
||||
|
||||
// ttl 秒钟之后, 这个key就会被移除
|
||||
if _, err = Client.Put(context.TODO(), key, val, clientv3.WithLease(resp.ID)); err != nil {
|
||||
return errors.New("lease key put fail : " + err.Error())
|
||||
}
|
||||
// the key will be kept forever
|
||||
if respChan, err = Client.KeepAlive(ctx, resp.ID); nil != err {
|
||||
return errors.New("lease keep alive fail : " + err.Error())
|
||||
}
|
||||
leaseData := &LeaseKeepAliveData{
|
||||
Key: key,
|
||||
StartTime: time.Now().Unix(),
|
||||
LastLeaseTime: 0,
|
||||
LeaseCnt: 0,
|
||||
HasFinish: false,
|
||||
LeaseFinishType: "",
|
||||
LeaseFinishTime: 0,
|
||||
LeaseDetail: nil,
|
||||
Data: make(map[string]interface{}),
|
||||
}
|
||||
// 监听 chan
|
||||
for ka := range respChan {
|
||||
leaseData.LeaseCnt++
|
||||
leaseData.LeaseDetail = ka
|
||||
leaseData.LastLeaseTime = time.Now().Unix()
|
||||
if nil != keepAliveHandler {
|
||||
keepAliveHandler(leaseData)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LeaseKeepAliveWithDuration 设置最大支持续期的时间, 中途可随时取消
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 8:05 下午 2021/11/23
|
||||
func LeaseKeepAliveWithDuration(ctx context.Context, key string, val string, ttl int64, keepAliveHandler LeaseKeepALiveHandler, cancelLeaseChan chan *LeaseKeepAliveData, maxCnt int64) (*LeaseKeepAliveData, error) {
|
||||
if ttl <= 0 {
|
||||
return nil, errors.New("lease time must be more than 0")
|
||||
}
|
||||
|
||||
if nil == cancelLeaseChan {
|
||||
cancelLeaseChan = make(chan *LeaseKeepAliveData, 1)
|
||||
}
|
||||
var cancelFunc context.CancelFunc
|
||||
if nil == ctx {
|
||||
ctx, cancelFunc = context.WithCancel(context.Background())
|
||||
} else {
|
||||
ctx, cancelFunc = context.WithCancel(ctx)
|
||||
}
|
||||
defer cancelFunc()
|
||||
var (
|
||||
resp *clientv3.LeaseGrantResponse
|
||||
respChan <-chan *clientv3.LeaseKeepAliveResponse
|
||||
err error
|
||||
)
|
||||
leaseData := &LeaseKeepAliveData{
|
||||
Key: key,
|
||||
StartTime: 0,
|
||||
LastLeaseTime: 0,
|
||||
LeaseCnt: 0,
|
||||
LeaseFinishType: "",
|
||||
LeaseFinishTime: 0,
|
||||
Data: make(map[string]interface{}),
|
||||
HasFinish: false,
|
||||
}
|
||||
// 创建一个 ttl 秒的租约
|
||||
if resp, err = Client.Grant(ctx, ttl); err != nil {
|
||||
return nil, errors.New("lease grant error : " + err.Error())
|
||||
}
|
||||
leaseData.StartTime = time.Now().Unix()
|
||||
|
||||
// ttl 秒钟之后, 这个key就会被移除
|
||||
if _, err = Client.Put(context.TODO(), key, val, clientv3.WithLease(resp.ID)); err != nil {
|
||||
return nil, errors.New("lease key put fail : " + err.Error())
|
||||
}
|
||||
// the key will be kept forever
|
||||
if respChan, err = Client.KeepAlive(ctx, resp.ID); nil != err {
|
||||
return nil, errors.New("lease keep alive fail : " + err.Error())
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-cancelLeaseChan:
|
||||
leaseData.HasFinish = true
|
||||
leaseData.LeaseFinishTime = time.Now().Unix()
|
||||
leaseData.LeaseFinishType = "SIGNAL_CANCEL"
|
||||
case leaseResp := <-respChan:
|
||||
leaseData.LeaseCnt++
|
||||
leaseData.LastLeaseTime = time.Now().Unix()
|
||||
leaseData.LeaseDetail = leaseResp
|
||||
if nil != keepAliveHandler {
|
||||
keepAliveHandler(leaseData)
|
||||
}
|
||||
if leaseData.LeaseCnt >= maxCnt {
|
||||
leaseData.HasFinish = true
|
||||
leaseData.LeaseFinishType = "OVER_MAX_CNT"
|
||||
leaseData.LeaseFinishTime = time.Now().Unix()
|
||||
}
|
||||
}
|
||||
if leaseData.HasFinish {
|
||||
break
|
||||
}
|
||||
}
|
||||
return leaseData, nil
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 11:40 上午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestLeaseOnce ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:37 下午 2021/11/23
|
||||
func TestLeaseOnce(t *testing.T) {
|
||||
key := "lock"
|
||||
fmt.Println(LeaseOnce(nil, key, "lock", 10))
|
||||
for i := 0; i < 15; i++ {
|
||||
fmt.Println(Get(nil, key, 1))
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLeaseKeepAliveForever ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:54 下午 2021/11/23
|
||||
func TestLeaseKeepAliveForever(t *testing.T) {
|
||||
key := "lock"
|
||||
keepAliveHandler := func(data *LeaseKeepAliveData) {
|
||||
fmt.Println(key, data.LeaseDetail.ID, data.LeaseDetail.TTL, data.LeaseCnt)
|
||||
}
|
||||
go func() {
|
||||
fmt.Println(LeaseKeepAliveForever(nil, key, "lock", 10, keepAliveHandler))
|
||||
}()
|
||||
for i := 0; i < 15; i++ {
|
||||
r, e := Get(nil, key, 1)
|
||||
fmt.Println("读取", r, e)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLeaseKeepAliveWithDuration ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:56 下午 2021/11/23
|
||||
func TestLeaseKeepAliveWithDuration(t *testing.T) {
|
||||
key := "lock"
|
||||
keepAliveHandler := func(data *LeaseKeepAliveData) {
|
||||
fmt.Println(key, data.LeaseDetail.ID, data.LeaseDetail.TTL, data.LeaseCnt)
|
||||
}
|
||||
go func() {
|
||||
fmt.Println(LeaseKeepAliveWithDuration(nil, key, "lock", 1, keepAliveHandler, nil, 5))
|
||||
}()
|
||||
for i := 0; i < 15; i++ {
|
||||
r, e := Get(nil, key, 1)
|
||||
fmt.Println("读取", r, e)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 12:09 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/mvcc/mvccpb"
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// Put put数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:09 下午 2021/11/23
|
||||
func Put(ctx context.Context, key string, val string, operateTimeout time.Duration) error {
|
||||
if operateTimeout <= 0 {
|
||||
operateTimeout = DefaultPutTimeout
|
||||
}
|
||||
var (
|
||||
cancel context.CancelFunc
|
||||
err error
|
||||
)
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
ctx, cancel = context.WithTimeout(ctx, operateTimeout)
|
||||
_, err = Client.Put(ctx, key, val)
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
|
||||
// GetWithOption 使用各种option选项读取数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:17 上午 2021/11/24
|
||||
func GetWithOption(ctx context.Context, key string, operateTimeout time.Duration, optionList ...clientv3.OpOption) (
|
||||
[]*mvccpb.KeyValue,
|
||||
error,
|
||||
) {
|
||||
if operateTimeout <= 0 {
|
||||
operateTimeout = DefaultGetTimeout
|
||||
}
|
||||
var (
|
||||
cancel context.CancelFunc
|
||||
err error
|
||||
result *clientv3.GetResponse
|
||||
)
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
ctx, cancel = context.WithTimeout(context.Background(), operateTimeout)
|
||||
defer cancel()
|
||||
if result, err = Client.Get(ctx, key, optionList...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Kvs, nil
|
||||
}
|
||||
|
||||
// Get 读取数据,按照key精确匹配
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:09 下午 2021/11/23
|
||||
func Get(ctx context.Context, key string, operateTimeout time.Duration) (
|
||||
[]*mvccpb.KeyValue,
|
||||
error,
|
||||
) {
|
||||
return GetWithOption(ctx, key, operateTimeout)
|
||||
}
|
||||
|
||||
// GetWithPrefix 使用key前缀查找
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:58 上午 2021/11/24
|
||||
func GetWithPrefix(ctx context.Context, keyPrefix string, operateTimeout time.Duration) (
|
||||
map[string]*mvccpb.KeyValue,
|
||||
error,
|
||||
) {
|
||||
var (
|
||||
result []*mvccpb.KeyValue
|
||||
err error
|
||||
)
|
||||
if result, err = GetWithOption(ctx, keyPrefix, operateTimeout, clientv3.WithPrefix()); nil != err {
|
||||
return make(map[string]*mvccpb.KeyValue), err
|
||||
}
|
||||
formatResult := make(map[string]*mvccpb.KeyValue)
|
||||
for _, item := range result {
|
||||
formatResult[string(item.Key)] = item
|
||||
}
|
||||
return formatResult, nil
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 12:27 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := InitEtcdClient(clientv3.Config{
|
||||
Endpoints: []string{"localhost:2379"},
|
||||
})
|
||||
if nil != err {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// TestPut ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:27 下午 2021/11/23
|
||||
func TestPut(t *testing.T) {
|
||||
fmt.Println(Put(nil, "name", "zhangdeman", 0))
|
||||
}
|
||||
|
||||
// TestGet ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:30 下午 2021/11/23
|
||||
func TestGet(t *testing.T) {
|
||||
fmt.Println(Get(nil, "name", 0))
|
||||
}
|
||||
|
||||
// TestGetWithPrefix 根据key前缀读取数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:01 上午 2021/11/24
|
||||
func TestGetWithPrefix(t *testing.T) {
|
||||
prefix := "/test/dir/"
|
||||
for i := 0; i < 10; i++ {
|
||||
_ = Put(nil, fmt.Sprintf("%s%d", prefix, i), util.GenRandomString("", 8), 0)
|
||||
}
|
||||
fmt.Println(GetWithPrefix(nil, prefix, 0))
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : 监听key的变化
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-23 2:58 下午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// WatchKeyWithOption ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:29 下午 2021/11/26
|
||||
func WatchKeyWithOption(ctx context.Context, watchKey string, callbackFunc WatcherHandler, optionList ...clientv3.OpOption) {
|
||||
if nil == callbackFunc {
|
||||
// 变化之后,没有任何逻辑处理,视为不需要监听变化
|
||||
return
|
||||
}
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
rch := Client.Watch(ctx, watchKey, optionList...) // <-chan WatchResponse
|
||||
for watchResp := range rch {
|
||||
for _, ev := range watchResp.Events {
|
||||
callbackFunc(ev)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WatchKey 监听key的变化,永久监听
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:58 下午 2021/11/23
|
||||
func WatchKey(ctx context.Context, watchKey string, callbackFunc WatcherHandler) {
|
||||
WatchKeyWithOption(ctx, watchKey, callbackFunc)
|
||||
}
|
||||
|
||||
// WatchWithKeyPrefix ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:30 下午 2021/11/26
|
||||
func WatchWithKeyPrefix(ctx context.Context, watchKey string, callbackFunc WatcherHandler) {
|
||||
WatchKeyWithOption(ctx, watchKey, callbackFunc, clientv3.WithPrefix())
|
||||
}
|
||||
|
||||
// WatchKeyWithCancel 可以随时取消的
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:16 下午 2021/11/23
|
||||
func WatchKeyWithCancel(ctx context.Context, watchKey string, callbackFunc WatcherHandler, cancelChan chan interface{}, cancelDealFunc CancelWatcherHandler) {
|
||||
if nil == callbackFunc {
|
||||
// 变化之后,没有任何逻辑处理,视为不需要监听变化
|
||||
return
|
||||
}
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
var (
|
||||
cancelFunc context.CancelFunc
|
||||
)
|
||||
ctx, cancelFunc = context.WithCancel(ctx)
|
||||
defer cancelFunc()
|
||||
|
||||
rch := Client.Watch(context.Background(), watchKey) // <-chan WatchResponse
|
||||
|
||||
hasFinish := false
|
||||
for {
|
||||
select {
|
||||
case cancelData := <-cancelChan:
|
||||
if nil != cancelDealFunc {
|
||||
cancelDealFunc(watchKey, cancelData)
|
||||
}
|
||||
hasFinish = true
|
||||
case watchResp := <-rch:
|
||||
for _, ev := range watchResp.Events {
|
||||
callbackFunc(ev)
|
||||
}
|
||||
}
|
||||
if hasFinish {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WatchKeyOnce 监听一次key
|
||||
//
|
||||
// timeout 若 <= 0 , 则会一直等待当前key发生变化为止
|
||||
//
|
||||
// timeout 若 > 0 , 则在制定时间内为监听到变化, 立即自动取消,
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:35 下午 2021/11/23
|
||||
func WatchKeyOnce(ctx context.Context, watchKey string, callbackFunc WatcherHandler, timeout time.Duration, timeoutHandler TimeoutWatcherHandler) {
|
||||
if nil == callbackFunc {
|
||||
// 变化之后,没有任何逻辑处理,视为不需要监听变化
|
||||
return
|
||||
}
|
||||
|
||||
if timeout == 0 {
|
||||
// 不指定超时时间,默认设置成int64最大值
|
||||
timeout = math.MaxInt16 * time.Second
|
||||
}
|
||||
|
||||
if nil == ctx {
|
||||
ctx = context.Background()
|
||||
}
|
||||
var (
|
||||
cancelFunc context.CancelFunc
|
||||
)
|
||||
ctx, cancelFunc = context.WithCancel(ctx)
|
||||
defer cancelFunc()
|
||||
rch := Client.Watch(ctx, watchKey) // <-chan WatchResponse
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
if nil != timeoutHandler {
|
||||
timeoutHandler(watchKey, timeout)
|
||||
}
|
||||
case watchResp := <-rch:
|
||||
for _, ev := range watchResp.Events {
|
||||
callbackFunc(ev)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
// Package etcd...
|
||||
//
|
||||
// Description : etcd...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-24 11:40 上午
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
)
|
||||
|
||||
// TestWatchKey ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:06 下午 2021/11/23
|
||||
func TestWatchKey(t *testing.T) {
|
||||
key := "name"
|
||||
dealFunc := func(data *clientv3.Event) {
|
||||
fmt.Println(string(data.Kv.Key), string(data.Kv.Value), data.Kv.Version, data.Kv.CreateRevision, data.Kv.ModRevision)
|
||||
}
|
||||
go func() {
|
||||
for i := 0; i < 30; i++ {
|
||||
_ = Put(nil, key, fmt.Sprintf("test-%d", i), 0)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
WatchKey(nil, key, dealFunc)
|
||||
}
|
||||
|
||||
// TestWatchKeyWithCancel ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:57 下午 2021/11/23
|
||||
func TestWatchKeyWithCancel(t *testing.T) {
|
||||
key := "name"
|
||||
dealFunc := func(data *clientv3.Event) {
|
||||
fmt.Println(string(data.Kv.Key), string(data.Kv.Value), data.Kv.Version, data.Kv.CreateRevision, data.Kv.ModRevision)
|
||||
}
|
||||
cancelFunc := func(key string, data interface{}) {
|
||||
fmt.Println("取消监听 : ", key, data)
|
||||
}
|
||||
cancelChan := make(chan interface{}, 1)
|
||||
go func() {
|
||||
for i := 0; i < 30; i++ {
|
||||
_ = Put(nil, key, fmt.Sprintf("test-%d", i), 0)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
time.Sleep(10 * time.Second)
|
||||
cancelChan <- "Hello World"
|
||||
}()
|
||||
WatchKeyWithCancel(nil, key, dealFunc, cancelChan, cancelFunc)
|
||||
}
|
||||
|
||||
// TestWatchKeyWithCancelByChangeCallback ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:27 下午 2021/11/23
|
||||
func TestWatchKeyWithCancelByChangeCallback(t *testing.T) {
|
||||
key := "name"
|
||||
cancelChan := make(chan interface{}, 1)
|
||||
|
||||
dealFunc := func(data *clientv3.Event) {
|
||||
fmt.Println(string(data.Kv.Key), string(data.Kv.Value), data.Kv.Version, data.Kv.CreateRevision, data.Kv.ModRevision)
|
||||
if string(data.Kv.Value) == "test-29" {
|
||||
cancelChan <- "Hello World!"
|
||||
}
|
||||
}
|
||||
|
||||
cancelFunc := func(key string, data interface{}) {
|
||||
fmt.Println("取消监听 : ", key, data)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 30; i++ {
|
||||
_ = Put(nil, key, fmt.Sprintf("test-%d", i), 0)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
WatchKeyWithCancel(nil, key, dealFunc, cancelChan, cancelFunc)
|
||||
}
|
||||
|
||||
// TestWatchKeyOnce ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:50 下午 2021/11/23
|
||||
func TestWatchKeyOnce(t *testing.T) {
|
||||
key := "name"
|
||||
dealFunc := func(data *clientv3.Event) {
|
||||
fmt.Println(string(data.Kv.Key), string(data.Kv.Value), data.Kv.Version, data.Kv.CreateRevision, data.Kv.ModRevision)
|
||||
}
|
||||
|
||||
timeoutFunc := func(key string, timeout time.Duration) {
|
||||
fmt.Println("监听超时", key, timeout)
|
||||
}
|
||||
|
||||
timeout := 10 * time.Second
|
||||
go func() {
|
||||
for i := 0; i < 30; i++ {
|
||||
_ = Put(nil, key, fmt.Sprintf("test-%d", i), 0)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
WatchKeyOnce(nil, key, dealFunc, timeout, timeoutFunc)
|
||||
}
|
||||
|
||||
// TestWatchKeyOnceForTimeout ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:53 下午 2021/11/23
|
||||
func TestWatchKeyOnceForTimeout(t *testing.T) {
|
||||
key := "name"
|
||||
dealFunc := func(data *clientv3.Event) {
|
||||
fmt.Println(string(data.Kv.Key), string(data.Kv.Value), data.Kv.Version, data.Kv.CreateRevision, data.Kv.ModRevision)
|
||||
}
|
||||
|
||||
timeoutFunc := func(key string, timeout time.Duration) {
|
||||
fmt.Println("监听超时", key, timeout)
|
||||
}
|
||||
|
||||
timeout := time.Second
|
||||
|
||||
WatchKeyOnce(nil, key, dealFunc, timeout, timeoutFunc)
|
||||
}
|
@ -10,107 +10,14 @@ package mysql
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/logger/wrapper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/logger"
|
||||
gormLogger "gorm.io/gorm/logger"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/logger/wrapper"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// NewDBClient ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:09 PM 2021/12/24
|
||||
func NewDBClient(masterConf *DBConfig, slaveConf *DBConfig, logConf *LogConfig, loggerInstance *zap.Logger, extraRequestFieldList []string) (*DBClient, error) {
|
||||
client := &DBClient{
|
||||
extraFieldList: extraRequestFieldList,
|
||||
}
|
||||
var err error
|
||||
// 日志初始化失败
|
||||
if client.loggerInstance, err = getLogInstance(logConf, loggerInstance); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
if client.master, err = GetDatabaseClient(masterConf, nil); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
if client.slave, err = GetDatabaseClient(slaveConf, nil); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// DBClient 包装日志实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:09 PM 2021/12/24
|
||||
type DBClient struct {
|
||||
loggerInstance *zap.Logger
|
||||
master *gorm.DB
|
||||
slave *gorm.DB
|
||||
extraFieldList []string
|
||||
}
|
||||
|
||||
// GetMaster 获取主库连接
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:28 PM 2021/12/24
|
||||
func (dc *DBClient) GetMaster(ctx *gin.Context) *gorm.DB {
|
||||
session := dc.master.Session(&gorm.Session{})
|
||||
session.Logger = dc.getLogger(ctx, session, "slave")
|
||||
return session
|
||||
}
|
||||
|
||||
// GetSlave 获取从库链接
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:29 PM 2021/12/24
|
||||
func (dc *DBClient) GetSlave(ctx *gin.Context) *gorm.DB {
|
||||
session := dc.slave.Session(&gorm.Session{})
|
||||
session.Logger = dc.getLogger(ctx, session, "slave")
|
||||
return session
|
||||
}
|
||||
|
||||
// getLogger 获取日志实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:45 PM 2021/12/24
|
||||
func (dc *DBClient) getLogger(ctx *gin.Context, dbClient *gorm.DB, node string) gormLogger.Interface {
|
||||
return wrapper.NewGormLoggerWithInstance(ctx, dbClient, dc.loggerInstance, node, dc.extraFieldList)
|
||||
}
|
||||
|
||||
// getLogInstance 获取日志实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:20 PM 2021/12/24
|
||||
func getLogInstance(logConf *LogConfig, loggerInstance *zap.Logger) (*zap.Logger, error) {
|
||||
if nil != loggerInstance {
|
||||
return loggerInstance, nil
|
||||
}
|
||||
logConfList := []logger.SetLoggerOptionFunc{logger.WithEncoder(logConf.Encoder), logger.WithCallerSkip(logConf.Skip), logger.WithCaller()}
|
||||
if logConf.ConsoleOutput {
|
||||
logConfList = append(logConfList, logger.WithConsoleOutput())
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
)
|
||||
if loggerInstance, err = logger.NewLogger(logConf.Level, logConf.SplitConfig, logConfList...); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return loggerInstance, nil
|
||||
}
|
||||
|
||||
// GetDatabaseClient 获取日志实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
@ -118,22 +25,35 @@ func getLogInstance(logConf *LogConfig, loggerInstance *zap.Logger) (*zap.Logger
|
||||
// Date : 10:49 下午 2021/3/1
|
||||
func GetDatabaseClient(conf *DBConfig, logConf *LogConfig) (*gorm.DB, error) {
|
||||
var (
|
||||
instance *gorm.DB
|
||||
err error
|
||||
loggerInstance *zap.Logger
|
||||
instance *gorm.DB
|
||||
err error
|
||||
)
|
||||
|
||||
if instance, err = gorm.Open(mysql.Open(buildConnectionDSN(conf)), &gorm.Config{}); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nil != logConf {
|
||||
if loggerInstance, err = getLogInstance(logConf, nil); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
instance.Logger = wrapper.NewGormLoggerWithInstance(nil, instance, loggerInstance, "", nil)
|
||||
if len(logConf.TraceFieldName) == 0 {
|
||||
logConf.TraceFieldName = defaultTraceFieldName
|
||||
}
|
||||
|
||||
splitConfigFuncList := []logger.SetRotateLogConfigFunc{
|
||||
logger.WithTimeIntervalType(logConf.SplitConfig.TimeIntervalType),
|
||||
logger.WithDivisionChar(logConf.SplitConfig.DivisionChar),
|
||||
logger.WithMaxAge(logConf.SplitConfig.MaxAge),
|
||||
}
|
||||
|
||||
splitConfig, _ := logger.NewRotateLogConfig(logConf.SplitConfig.LogPath, logConf.SplitConfig.LogFileName, splitConfigFuncList...)
|
||||
|
||||
if instance.Logger, err = wrapper.NewGormV2(
|
||||
logConf.Level,
|
||||
logConf.ConsoleOutput,
|
||||
logConf.Encoder,
|
||||
splitConfig,
|
||||
logConf.TraceFieldName,
|
||||
logConf.Skip); nil != err {
|
||||
return nil, CreateDBLogError(err)
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
|
@ -42,3 +42,8 @@ type LogConfig struct {
|
||||
TraceFieldName string
|
||||
Skip int
|
||||
}
|
||||
|
||||
const (
|
||||
// defaultTraceFieldName 默认trace_id字段
|
||||
defaultTraceFieldName = "trace_id"
|
||||
)
|
||||
|
@ -1,139 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,301 +0,0 @@
|
||||
// Package redis ...
|
||||
//
|
||||
// Description : redis ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-26 21:07 下午
|
||||
package redis
|
||||
|
||||
// FullServerInfo 获取服务器信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:07 下午 2021/11/26
|
||||
type FullServerInfo struct {
|
||||
ServerInfo *ServerInfo `json:"server_info"`
|
||||
ClientInfo *ClientInfo `json:"client_info"`
|
||||
MemoryInfo *MemoryInfo `json:"memory_info"`
|
||||
Persistence *Persistence `json:"persistence"`
|
||||
Stats *Stats `json:"stats"`
|
||||
Replication *Replication `json:"replication"`
|
||||
CPU *CPU `json:"cpu"`
|
||||
CommandStats []CmdStat `json:"command_stats"`
|
||||
Keyspace []DB `json:"keyspace"`
|
||||
Cluster *Cluster `json:"cluster"`
|
||||
ErrorStats []Error `json:"error_stats"`
|
||||
Modules interface{} `json:"modules"`
|
||||
}
|
||||
|
||||
// ServerInfo 服务器信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:09 下午 2021/11/26
|
||||
type ServerInfo struct {
|
||||
RedisVersion string `json:"redis_version" yaml:"redis_version"` // Redis 服务器版本
|
||||
RedisGitSha1 string `json:"redis_git_sha1" yaml:"redis_git_sha1"` // Git SHA1
|
||||
RedisGitDirty string `json:"redis_git_dirty" yaml:"redis_git_dirty"` // Git dirty flag
|
||||
RedisBuildID string `json:"redis_build_id" yaml:"redis_build_id"` // 构建ID
|
||||
RedisMode string `json:"redis_mode" yaml:"redis_mode"` // 运行模式(“独立”,“哨兵”或“集群”)
|
||||
OS string `json:"os" yaml:"os"` // Redis 服务器的宿主操作系统
|
||||
ArchBits string `json:"arch_bits" yaml:"arch_bits"` // 架构(32 或 64 位)
|
||||
MultiplexingApi string `json:"multiplexing_api" yaml:"multiplexing_api"` // Redis 所使用的事件处理机制
|
||||
AtomicvarApi string `json:"atomicvar_api" yaml:"atomicvar_api"` // 原子处理api
|
||||
GCCVersion string `json:"gcc_version" yaml:"gcc_version"` // 编译 Redis 时所使用的 GCC 版本
|
||||
ProcessID int `json:"process_id" yaml:"process_id"` // 服务器进程的 PID
|
||||
ProcessSupervised string `json:"process_supervised" yaml:"process_supervised"` // 是否有进程监控
|
||||
RunID string `json:"run_id" yaml:"run_id"` // Redis 服务器的随机标识符(用于 Sentinel 和集群)
|
||||
TCPPort int `json:"tcp_port" yaml:"tcp_port"` // TCP/IP 监听端口
|
||||
ServerTimeUsec int64 `json:"server_time_usec" yaml:"server_time_usec"` // 当前服务器时间,微秒
|
||||
UptimeInSeconds int64 `json:"uptime_in_seconds" yaml:"uptime_in_seconds"` // 自 Redis 服务器启动以来,经过的秒数
|
||||
UptimeInDays int64 `json:"uptime_in_days" yaml:"uptime_in_days"` // 自 Redis 服务器启动以来,经过的天数
|
||||
Hz int64 `json:"hz" yaml:"hz"` // redis内部调度(进行关闭timeout的客户端,删除过期key等等)频率,程序规定serverCron每秒运行10次。
|
||||
ConfiguredHz int64 `json:"configured_hz" yaml:"configured_hz"` // 服务器的频率设置
|
||||
LRUClock int64 `json:"lru_clock" yaml:"lru_clock"` // 以秒为单位进行自增的时钟,用于 LRU 管理
|
||||
Executable string `json:"executable" yaml:"executable"` // 可执行文件位置
|
||||
ConfigFile string `json:"config_file" yaml:"config_file"` // 服务所使用的配置文件
|
||||
IOThreadsActive int `json:"io_threads_active" yaml:"io_threads_active"` // 活跃的io线程数
|
||||
}
|
||||
|
||||
// ClientInfo 客户端信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:29 下午 2021/11/26
|
||||
type ClientInfo struct {
|
||||
ConnectedClients int `json:"connected_clients" yaml:"connected_clients"` // 客户端连接数
|
||||
ClusterConnections int `json:"cluster_connections" yaml:"cluster_connections"` // 集群连接数
|
||||
MaxClients int `json:"maxclients" yaml:"max_clients"` // 最大客户端连接数
|
||||
ClientRecentMaxInputBuffer int64 `json:"client_recent_max_input_buffer" yaml:"client_recent_max_input_buffer"` // 最近最大输入缓存
|
||||
ClientRecentMaxOutputBuffer int64 `json:"client_recent_max_output_buffer" yaml:"client_recent_max_output_buffer"` // 最近最大输出缓存
|
||||
BlockedClients int `json:"blocked_clients" yaml:"blocked_clients"` // 阻塞客户端数量, 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
|
||||
TrackingClients int `json:"tracking_clients" yaml:"tracking_clients"` // tracking_clients
|
||||
ClientsInTimeoutTable int `json:"clients_in_timeout_table" yaml:"clients_in_timeout_table"` // clients_in_timeout_table
|
||||
}
|
||||
|
||||
// MemoryInfo 内存使用信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 22:08 下午 2021/11/26
|
||||
type MemoryInfo struct {
|
||||
UsedMemory int64 `json:"used_memory" yaml:"used_memory"` // 由 Redis 分配器分配的内存总量,以字节(byte)为单位
|
||||
UsedMemoryHuman string `json:"used_memory_human" yaml:"used_memory_human"` // UsedMemory 可读化表示
|
||||
UsedMemoryRss int64 `json:"used_memory_rss" yaml:"used_memory_rss"` // 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致。
|
||||
UsedMemoryRssHuman string `json:"used_memory_rss_human" yaml:"used_memory_rss_human"` // UsedMemoryRssHuman 可读化表示
|
||||
UsedMemoryPeak int64 `json:"used_memory_peak" yaml:"used_memory_peak"` // Redis 的内存消耗峰值(以字节为单位)
|
||||
UsedMemoryPeakHuman string `json:"used_memory_peak_human" yaml:"used_memory_peak_human"` // UsedMemoryPeak 可读化表示
|
||||
UsedMemoryPeakPerc string `json:"used_memory_peak_perc" yaml:"used_memory_peak_perc"` // 峰值系统内存使用率
|
||||
UsedMemoryOverhead int64 `json:"used_memory_overhead" yaml:"used_memory_overhead"` // Redis为了维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF重写缓冲区和主从复制的backlog
|
||||
UsedMemoryStartup int64 `json:"used_memory_startup" yaml:"used_memory_startup"` // Redis服务器启动时消耗的内存
|
||||
UsedMemoryDataset int64 `json:"used_memory_dataset" yaml:"used_memory_dataset"` // 数据占用的内存大小,即used_memory-used_memory_overhead
|
||||
UsedMemoryDatasetPerc int64 `json:"used_memory_dataset_perc" yaml:"used_memory_dataset_perc"` // 数据占用的内存大小的百分比,100%*(used_memory_dataset/(used_memory-used_memory_startup))
|
||||
AllocatorAllocated int64 `json:"allocator_allocated" yaml:"allocator_allocated"` // 内存分配器申请的内存,以字节为单位
|
||||
AllocatorActive int64 `json:"allocator_active" yaml:"allocator_active"` // 内存分配器正在使用的内存,以字节为单位
|
||||
AllocatorResident int64 `json:"allocator_resident" yaml:"allocator_resident"` // 内存分配器的常驻内存,以字节为单位
|
||||
TotalSystemMemory int64 `json:"total_system_memory" yaml:"total_system_memory"` // 操作系统内存(以字节为单位)
|
||||
TotalSystemMemoryHuman string `json:"total_system_memory_human" yaml:"total_system_memory_human"` // TotalSystemMemory 可读化表示
|
||||
UsedMemoryLua int64 `json:"used_memory_lua" yaml:"used_memory_lua"` // Lua脚本存储占用的内存(以字节为单位)
|
||||
UsedMemoryLuaHuman int64 `json:"used_memory_lua_human" yaml:"used_memory_lua_human"` // UsedMemoryLua 可读化表示
|
||||
UsedMemoryScripts int64 `json:"used_memory_scripts" yaml:"used_memory_scripts"` // Lua脚本使用的内存大小(以字节为单位)
|
||||
UsedMemoryScriptsHuman int64 `json:"used_memory_scripts_human" yaml:"used_memory_scripts_human"` // UsedMemoryScripts 可读化表示
|
||||
NumberOfCachedScripts int64 `json:"number_of_cached_scripts" yaml:"number_of_cached_scripts"` // 缓存的lua脚本数量
|
||||
Maxmemory int64 `json:"maxmemory" yaml:"maxmemory"` // Redis实例的最大内存配置(以字节为单位)
|
||||
MaxmemoryHuman int64 `json:"maxmemory_human" yaml:"maxmemory_human"` // Maxmemory 可读化表示
|
||||
MaxmemoryPolicy string `json:"maxmemory_policy" yaml:"maxmemory_policy"` // 当数据达到最大内存之后的淘汰策略
|
||||
AllocatorFragRatio float64 `json:"allocator_frag_ratio" yaml:"allocator_frag_ratio"` // 内存分配器碎片比例
|
||||
AllocatorFragBytes int64 `json:"allocator_frag_bytes" yaml:"allocator_frag_bytes"` // 内存分配器碎片大小,以字节为单位
|
||||
AllocatorRssRatio float64 `json:"allocator_rss_ratio" yaml:"allocator_rss_ratio"` // 从操作系统角度看, 内存分配器碎片比例
|
||||
AllocatorRssBytes int64 `json:"allocator_rss_bytes" yaml:"allocator_rss_bytes"` // 从操作系统角度看, 内存分配器碎片大小,以字节为单位
|
||||
RssOverheadRatio float64 `json:"rss_overhead_ratio" yaml:"rss_overhead_ratio"` // 从操作系统角度看, 开销的比例
|
||||
RssOverheadBytes int64 `json:"rss_overhead_bytes" yaml:"rss_overhead_bytes"` // 从操作系统角度看, 开销的大小, 以字节为单位
|
||||
MemFragmentationRatio float64 `json:"mem_fragmentation_ratio" yaml:"mem_fragmentation_ratio"` // 碎片率,used_memory_rss/ used_memory,正常情况下稍大于1。低于1,Redis实例可能会把部分数据交换到硬盘上,内存交换会严重影响Redis的性能,所以应该增加可用物理内存。大于1.5表示碎片过多。额外碎片的产生是由于Redis释放了内存块,但内存分配器并没有返回内存给操作系统,这个内存分配器是在编译时指定的,可以是libc、jemalloc或者tcmalloc。
|
||||
MemFragmentationBytes int64 `json:"mem_fragmentation_bytes" yaml:"mem_fragmentation_bytes"` // 内存碎片大小(字节表示)
|
||||
MemNotCountedForEvict int64 `json:"mem_not_counted_for_evict" yaml:"mem_not_counted_for_evict"` // 不应驱逐的内存大小,以字节为单位
|
||||
MemReplicationBacklog int64 `json:"mem_replication_backlog" yaml:"mem_replication_backlog"` // 复制backlog的内存大小, 以字节为单位
|
||||
MemClientsSlaves int64 `json:"mem_clients_slaves" yaml:"mem_clients_slaves"` // mem_clients_slaves
|
||||
MemClientsNormal int64 `json:"mem_clients_normal" yaml:"mem_clients_normal"` // mem_clients_normal
|
||||
MemAofBuffer int64 `json:"mem_aof_buffer" yaml:"mem_aof_buffer"` // AOF内存缓冲区大小
|
||||
MemAllocator string `json:"mem_allocator" yaml:"mem_allocator"` // 内存分配器,Redis支持glibc’s malloc、jemalloc11、tcmalloc几种不同的内存分配器,每个分配器在内存分配和碎片上都有不同的实现。不建议普通管理员修改Redis默认内存分配器,因为这需要完全理解这几种内存分配器的差异,也要重新编译Redis。
|
||||
ActiveDefragRunning int64 `json:"active_defrag_running" yaml:"active_defrag_running"` // defrag:表示内存碎片整理, 0表示没有活动的defrag任务正在运行,1表示有活动的defrag任务正在运行
|
||||
LazyfreePendingObjects int64 `json:"lazyfree_pending_objects" yaml:"lazyfree_pending_objects"` // 延迟释放的挂起对象, 0表示不存在
|
||||
LazyfreedObjects int64 `json:"lazyfreed_objects" yaml:"lazyfreed_objects"` // 延迟释放的对象数量
|
||||
}
|
||||
|
||||
// Persistence 持久化信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 22:15 下午 2021/11/26
|
||||
type Persistence struct {
|
||||
Loading int `json:"loading" yaml:"loading"` // 服务器是否正在进行持久化 0 - 否 1 -是
|
||||
CurrentCowSize int `json:"current_cow_size" yaml:"current_cow_size"` // current_cow_size
|
||||
CurrentCowSizeAge int `json:"current_cow_size_age" yaml:"current_cow_size_age"` // current_cow_size_age
|
||||
CurrentForkPerc float64 `json:"current_fork_perc" yaml:"current_fork_perc"` // current_fork_perc
|
||||
CurrentSaveKeysProcessed int `json:"current_save_keys_processed" yaml:"current_save_keys_processed"` // current_save_keys_processed
|
||||
CurrentSaveKeysTotal int64 `json:"current_save_keys_total" yaml:"current_save_keys_total"` // current_save_keys_total
|
||||
RdbChangesSinceLastSave int64 `json:"rdb_changes_since_last_save" yaml:"rdb_changes_since_last_save"` // 离最近一次成功生成rdb文件,写入命令的个数,即有多少个写入命令没有持久化
|
||||
RdbBgsaveInProgress int `json:"rdb_bgsave_in_progress" yaml:"rdb_bgsave_in_progress"` // 服务器是否正在创建rdb文件 0 - 否 1 - 是
|
||||
RdbLastSaveTime int64 `json:"rdb_last_save_time" yaml:"rdb_last_save_time"` // 最近一次创建rdb文件的时间戳,单位秒
|
||||
RdbLastBgsaveStatus string `json:"rdb_last_bgsave_status" yaml:"rdb_last_bgsave_status"` // 最近一次rdb持久化是否成功 ok 成功
|
||||
RdbLastBgsaveTimeSec int64 `json:"rdb_last_bgsave_time_sec" yaml:"rdb_last_bgsave_time_sec"` // 最近一次成功生成rdb文件耗时秒数
|
||||
RdbCurrentBgsaveTimeSec int64 `json:"rdb_current_bgsave_time_sec" yaml:"rdb_current_bgsave_time_sec"` // 如果服务器正在创建rdb文件,那么这个字段记录的就是当前的创建操作已经耗费的秒数
|
||||
RdbLastCowSize int64 `json:"rdb_last_cow_size" yaml:"rdb_last_cow_size"` // RDB过程中父进程与子进程相比执行了多少修改(包括读缓冲区,写缓冲区,数据修改等)。
|
||||
AofEnabled int `json:"aof_enabled" yaml:"aof_enabled"` // 是否开启了AOF 0 - 否 1 - 是
|
||||
AofRewriteInProgress int `json:"aof_rewrite_in_progress" yaml:"aof_rewrite_in_progress"` // 标识aof的rewrite操作是否在进行中 0 - 否 1- 是
|
||||
AofRewriteScheduled int `json:"aof_rewrite_scheduled" yaml:"aof_rewrite_scheduled"` // rewrite任务计划,当客户端发送bgrewriteaof指令,如果当前rewrite子进程正在执行,那么将客户端请求的bgrewriteaof变为计划任务,待aof子进程结束后执行rewrite
|
||||
AofLastRewriteTimeSec int `json:"aof_last_rewrite_time_sec" yaml:"aof_last_rewrite_time_sec"` // 最近一次aof rewrite耗费的时长
|
||||
AofCurrentRewriteTimeSec int `json:"aof_current_rewrite_time_sec" yaml:"aof_current_rewrite_time_sec"` // 如果rewrite操作正在进行,则记录所使用的时间,单位秒
|
||||
AofLastBgrewriteStatus string `json:"aof_last_bgrewrite_status" yaml:"aof_last_bgrewrite_status"` // 上次 bgrewrite aof 操作的状态 ok 成功
|
||||
AofLastWriteStatus string `json:"aof_last_write_status" yaml:"aof_last_write_status"` // 上次aof写入状态
|
||||
AofLastCowSize int64 `json:"aof_last_cow_size" yaml:"aof_last_cow_size"` // AOF过程中父进程与子进程相比执行了多少修改(包括读缓冲区,写缓冲区,数据修改等)
|
||||
IOThreadedReadsProcessed int `json:"io_threaded_reads_processed" yaml:"io_threaded_reads_processed"` // 读取线程数
|
||||
IOThreadedWritesProcessed int `json:"io_threaded_writes_processed" yaml:"io_threaded_writes_processed"` // 写入线程数
|
||||
}
|
||||
|
||||
// Stats 服务运行状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:57 下午 2021/11/26
|
||||
type Stats struct {
|
||||
TotalConnectionsReceived int64 `json:"total_connections_received" yaml:"total_connections_received"` // 所有连接数, 累积值, 只增不减, 连接断开也不会减少
|
||||
TotalCommandsProcessed int64 `json:"total_commands_processed" yaml:"total_commands_processed"` // 服务器执行的命令数 累积值, 只增不减
|
||||
InstantaneousPpsPerSec int `json:"instantaneous_pps_per_sec" yaml:"instantaneous_pps_per_sec"` // 每秒执行的命令数
|
||||
TotalNetInputBytes int64 `json:"total_net_input_bytes" yaml:"total_net_input_bytes"` // 网络流量-流入 以字节(byte)为单位
|
||||
TotalNetOutputBytes int64 `json:"total_net_output_bytes" yaml:"total_net_output_bytes"` // 网络流量-流出 以字节(byte)为单位
|
||||
InstantaneousInputKbps float64 `json:"instantaneous_input_kbps" yaml:"instantaneous_input_kbps"` // 网络流量-流入-KB/s
|
||||
InstantaneousOutputKbps float64 `json:"instantaneous_output_kbps" yaml:"instantaneous_output_kbps"` // 网络流量-流出-KB/s
|
||||
RejectedConnections int64 `json:"rejected_connections" yaml:"rejected_connections"` // 因达到最大连接数而被拒绝的连接数量
|
||||
SyncFull int64 `json:"sync_full" yaml:"sync_full"` // 主从全量同步的次数
|
||||
SyncPartialOk int64 `json:"sync_partial_ok" yaml:"sync_partial_ok"` // 主从部分同步成功的次数
|
||||
SyncPartialErr int64 `json:"sync_partial_err" yaml:"sync_partial_err"` // 主从部分同步失败次数
|
||||
ExpiredKeys int `json:"expired_keys" yaml:"expired_keys"` // 过期key的数量
|
||||
ExpiredStalePerc float64 `json:"expired_stale_perc" yaml:"expired_stale_perc"` // 过期过时的百分比
|
||||
ExpiredTimeCapReachedCount int64 `json:"expired_time_cap_reached_count" yaml:"expired_time_cap_reached_count"` // 过期时间达到上限的数量
|
||||
ExpireCycleCpuMilliseconds int64 `json:"expire_cycle_cpu_milliseconds" yaml:"expire_cycle_cpu_milliseconds"` // 过期循环CPU毫秒数
|
||||
EvictedKeys int64 `json:"evicted_keys" yaml:"evicted_keys"` // 超过 maxmemory 之后, 剔除的 key 的数量
|
||||
KeyspaceHits int64 `json:"keyspace_hits" yaml:"keyspace_hits"` // 访问命中次数
|
||||
KeyspaceMisses int64 `json:"keyspace_misses" yaml:"keyspace_misses"` // 访问未命中次数
|
||||
PubsubChannels int64 `json:"pubsub_channels" yaml:"pubsub_channels"` // 当前频道数量 发布 - 订阅 模式
|
||||
PubsubPatterns int64 `json:"pubsub_patterns" yaml:"pubsub_patterns"` // 当前使用中的模式数量
|
||||
LatestForkUsec int64 `json:"latest_fork_usec" yaml:"latest_fork_usec"` // 最近一次fork 操作消耗的时间, 单位微秒
|
||||
TotalForks int64 `json:"total_forks" yaml:"total_forks"` // fork 的总次数
|
||||
MigrateCachedSockets int64 `json:"migrate_cached_sockets" yaml:"migrate_cached_sockets"` // 记录当前 Redis 正在 migrate 操作的目标 Redis 个数, 例如 A 向 B 和 C 执行 migrate操作, 这个值为2
|
||||
SlaveExpiresTrackedKeys int64 `json:"slave_expires_tracked_keys" yaml:"slave_expires_tracked_keys"` // 从实例到期的 key 的数量
|
||||
ActiveDefragHits int64 `json:"active_defrag_hits" yaml:"active_defrag_hits"` // 主动碎片整理命中次数
|
||||
ActiveDefragMisses int64 `json:"active_defrag_misses" yaml:"active_defrag_misses"` // 主动碎片整理未命中次数
|
||||
ActiveDefragKeyHits int64 `json:"active_defrag_key_hits" yaml:"active_defrag_key_hits"` // 主动整理碎片, key命中次数
|
||||
ActiveDefragKeyMisses int64 `json:"active_defrag_key_misses" yaml:"active_defrag_key_misses"` // 主动整理碎片, key未命中次数
|
||||
TrackingTotalKeys int64 `json:"tracking_total_keys" yaml:"tracking_total_keys"` // key 查询的总数
|
||||
TrackingTotalItems int64 `json:"tracking_total_items" yaml:"tracking_total_items"` // item查询的总数
|
||||
TrackingTotalPrefixes int64 `json:"tracking_total_prefixes" yaml:"tracking_total_prefixes"` // 前缀查询的总数
|
||||
UnexpectedErrorReplies int64 `json:"unexpected_error_replies" yaml:"unexpected_error_replies"` // unexpected 异常响应次数
|
||||
TotalErrorReplies int64 `json:"total_error_replies" yaml:"total_error_replies"` // 异常响应总次数
|
||||
DumpPayloadSanitizations int64 `json:"dump_payload_sanitizations" yaml:"dump_payload_sanitizations"` // dump_payload_sanitizations
|
||||
TotalReadsProcessed int64 `json:"total_reads_processed" yaml:"total_reads_processed"` // 正在读取的请求数
|
||||
TotalWritesProcessed int64 `json:"total_writes_processed" yaml:"total_writes_processed"` // 正在写入的请求数
|
||||
IOThreadedReadsProcessed int64 `json:"io_threaded_reads_processed" yaml:"io_threaded_reads_processed"` // 正在读取的线程数
|
||||
IOThreadedWritesProcessed int64 `json:"io_threaded_writes_processed" yaml:"io_threaded_writes_processed"` // 正在写入的线程数
|
||||
}
|
||||
|
||||
// Replication 复制相关
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:42 上午 2021/11/27
|
||||
type Replication struct {
|
||||
Role string `json:"role" yaml:"role"` // 节点的角色 master / slave
|
||||
ReplBacklogActive int `json:"repl_backlog_active" yaml:"repl_backlog_active"` // 复制缓冲区是否开启 0 - 未开启 1 - 已开启
|
||||
ReplBacklogSize int64 `json:"repl_backlog_size" yaml:"repl_backlog_size"` // 复制缓冲区大小(以字节为单位)
|
||||
ReplBacklogFirstByteOffset int64 `json:"repl_backlog_first_byte_offset" yaml:"repl_backlog_first_byte_offset"` // 复制缓冲区里偏移量的大小
|
||||
ReplBacklogHistlen int64 `json:"repl_backlog_histlen" yaml:"repl_backlog_histlen"` // 此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小
|
||||
ConnectedSlaves int `json:"connected_slaves" yaml:"connected_slaves"` // 仅主节点属性 : 连接的从节点数量
|
||||
MasterFailoverState string `json:"master_failover_state" yaml:"master_failover_state"` // 仅主节点 : 故障转移状态 no-failover 无故障转移
|
||||
MasterReplid string `json:"master_replid" yaml:"master_replid"` // 仅主节点 : 实例启动的随机字符串
|
||||
MasterReplid2 string `json:"master_replid2" yaml:"master_replid2"` // 仅主节点 : 实例启动的随机字符串2
|
||||
MasterReplOffset int64 `json:"master_repl_offset" yaml:"master_repl_offset"` // 仅主节点 : 主从同步偏移量
|
||||
SecondReplOffset int64 `json:"second_repl_offset" yaml:"second_repl_offset"` // 仅主节点 : 主从同步偏移量2
|
||||
MasterHost string `json:"master_host" yaml:"master_host"` // 仅从节点 : 主节点host
|
||||
MasterPort int `json:"master_port" yaml:"master_port"` // 仅从节点 : 主节点端口
|
||||
MasterLinkStatus string `json:"master_link_status" yaml:"master_link_status"` // 仅从节点 : 与主节点连接状态 up - 正常连接 down - 断开
|
||||
MasterLastIOSecondsAgo int `json:"master_last_io_seconds_ago" yaml:"master_last_io_seconds_ago"` // 仅从节点 : 主节点与从节点最后通信的时间间隔, 单位: s
|
||||
MasterSyncInProgress int `json:"master_sync_in_progress" yaml:"master_sync_in_progress"` // 仅从节点 : 从节点是否正在全量同步主节点rdb文件 0 - 否 1 - 是
|
||||
SlaveReplOffset int64 `json:"slave_repl_offset" yaml:"slave_repl_offset"` // 仅从节点 : 复制偏移量
|
||||
SlavePriority int `json:"slave_priority" yaml:"slave_priority"` // 仅从节点 : 从节点优先级
|
||||
SlaveReadOnly int `json:"slave_read_only" yaml:"slave_read_only"` // 仅从节点 : 从节点是否只读 0 - 否 1 - 是
|
||||
SlaveList []SlaveNode `json:"slave_list" yaml:"slave_list"` // 从节点列表
|
||||
}
|
||||
|
||||
// SlaveNode 从库数据结构,基于原始数据解析 eg : slave0:ip=x.x.x.x,port=6379,state=online,offset=123456,lag=1
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:51 上午 2021/11/27
|
||||
type SlaveNode struct {
|
||||
ID string `json:"id" yaml:"id"` // 从库ID
|
||||
IP string `json:"ip" yaml:"ip"` // 从库IP
|
||||
Port int `json:"port" yaml:"port"` // 从库端口
|
||||
State string `json:"state" yaml:"state"` // 从库状态 online - 在线 offline - 离线
|
||||
Offset int64 `json:"offset" yaml:"offset"` // 数据偏移量
|
||||
Lag int64 `json:"lag" yaml:"lag"` // 数据延迟量大小
|
||||
}
|
||||
|
||||
// CPU 信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:54 上午 2021/11/27
|
||||
type CPU struct {
|
||||
UsedCpuSys float64 `json:"used_cpu_sys" yaml:"used_cpu_sys"` // Redis主进程在内核态所占用CPU时钟总和
|
||||
UsedCpuUser float64 `json:"used_cpu_user" yaml:"used_cpu_user"` // Redis主进程在用户态所占用CPU时钟总和
|
||||
UsedCpuSysChildren float64 `json:"used_cpu_sys_children" yaml:"used_cpu_sys_children"` // Redis子进程在内核态所占用CPU时钟总和
|
||||
UsedCpuUserChildren float64 `json:"used_cpu_user_children" yaml:"used_cpu_user_children"` // Redis子进程在用户态所占用CPU时钟总和
|
||||
}
|
||||
|
||||
// CmdStat 指令状态 eg : cmdstat_get:calls=1,usec=42121,usec_per_call=42121.00,rejected_calls=0,failed_calls=0
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:02 上午 2021/11/27
|
||||
type CmdStat struct {
|
||||
Cmd string `json:"cmd" yaml:"cmd"` // 执行的指令
|
||||
Calls int64 `json:"calls" yaml:"calls"` // 执行了多少次
|
||||
TotalUsedTime float64 `json:"total_used_time" yaml:"total_used_time"` // 累计总耗时 微秒
|
||||
AvgUsedTime float64 `json:"avg_used_time" yaml:"avg_used_time"` // 平均耗时 微秒
|
||||
RejectedCalls int64 `json:"rejected_calls" yaml:"rejected_calls"` // 拒绝执行指令次数
|
||||
FailedCalls int64 `json:"failed_calls" yaml:"failed_calls"` // 指令执行失败次数
|
||||
SuccessCalls int64 `json:"success_calls" yaml:"success_calls"` // 指令执行成功次数 Calls - FailedCalls
|
||||
}
|
||||
|
||||
// DB 数据库的数据结构, eg : db0:keys=3,expires=0,avg_ttl=0
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:09 上午 2021/11/27
|
||||
type DB struct {
|
||||
Name string `json:"name" yaml:"name"` // 数据库名称
|
||||
Keys int64 `json:"keys" yaml:"keys"` // 数据库key的数量
|
||||
Expires int64 `json:"expires" yaml:"expires"` // 数据库过期key的数量
|
||||
AvgTTL int64 `json:"avg_ttl" yaml:"avg_ttl"` // 平均存活时间
|
||||
}
|
||||
|
||||
// Cluster ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:13 上午 2021/11/27
|
||||
type Cluster struct {
|
||||
ClusterEnabled int `json:"cluster_enabled" yaml:"cluster_enabled"` // 是否启用 0 - 否 1 - 是
|
||||
}
|
||||
|
||||
// Error 错误的状态 eg : errorstat_WRONGTYPE:count=4615
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:16 上午 2021/11/27
|
||||
type Error struct {
|
||||
Type string `json:"type" yaml:"type"` // 错误类型
|
||||
Count int64 `json:"count" yaml:"count"` // 错误出现次数
|
||||
}
|
@ -1,326 +0,0 @@
|
||||
// Package redis ...
|
||||
//
|
||||
// Description : redis 系统信息监控
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-27 12:22 下午
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/convert"
|
||||
|
||||
yml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
// GetRedisServerInfo 获取 redis server info
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:24 下午 2021/11/27
|
||||
func GetRedisServerInfo(client *redis.Client) (*ServerInfo, error) {
|
||||
var result ServerInfo
|
||||
if err := infoToStruct(client, "server", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetMemoryInfo 获取内存信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:59 下午 2021/11/27
|
||||
func GetMemoryInfo(client *redis.Client) (*MemoryInfo, error) {
|
||||
var result MemoryInfo
|
||||
if err := infoToStruct(client, "memory", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetClientInfo 获取客户端信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:10 下午 2021/11/27
|
||||
func GetClientInfo(client *redis.Client) (*ClientInfo, error) {
|
||||
var result ClientInfo
|
||||
if err := infoToStruct(client, "clients", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetPersistence 获取持久化相关信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:11 下午 2021/11/27
|
||||
func GetPersistence(client *redis.Client) (*Persistence, error) {
|
||||
var result Persistence
|
||||
if err := infoToStruct(client, "persistence", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetStats 获取状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:19 下午 2021/11/27
|
||||
func GetStats(client *redis.Client) (*Stats, error) {
|
||||
var result Stats
|
||||
if err := infoToStruct(client, "stats", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetReplication 复制相关信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:23 下午 2021/11/27
|
||||
func GetReplication(client *redis.Client) (*Replication, error) {
|
||||
var result Replication
|
||||
if err := infoToStruct(client, "replication", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
result.SlaveList = GetSlaveList(client)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetSlaveList 获取从库信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:26 下午 2021/11/27
|
||||
func GetSlaveList(client *redis.Client) []SlaveNode {
|
||||
// 解析从库信息
|
||||
slaveList := make([]SlaveNode, 0)
|
||||
var data map[string]string
|
||||
_ = infoToStruct(client, "replication", &data)
|
||||
slaveKey := []string{"slave0", "slave1", "slave2", "slave3", "slave4", "slave5", "slave6", "slave7", "slave8", "slave9"}
|
||||
for k, v := range data {
|
||||
isSlave := false
|
||||
for _, item := range slaveKey {
|
||||
if strings.Contains(k, item) {
|
||||
isSlave = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isSlave {
|
||||
continue
|
||||
}
|
||||
|
||||
vArr := strings.Split(v, ",")
|
||||
if len(vArr) < 3 {
|
||||
continue
|
||||
}
|
||||
slave := SlaveNode{
|
||||
ID: k,
|
||||
IP: "",
|
||||
Port: 0,
|
||||
State: "",
|
||||
Offset: 0,
|
||||
Lag: 0,
|
||||
}
|
||||
for _, prop := range vArr {
|
||||
propArr := strings.Split(prop, "=")
|
||||
if len(propArr) != 2 {
|
||||
continue
|
||||
}
|
||||
switch strings.ToLower(propArr[0]) {
|
||||
case "ip":
|
||||
slave.IP = propArr[1]
|
||||
case "port":
|
||||
_ = convert.ConvertAssign(&slave.Port, propArr[1])
|
||||
case "state":
|
||||
slave.State = propArr[1]
|
||||
case "offset":
|
||||
_ = convert.ConvertAssign(&slave.Offset, propArr[1])
|
||||
case "lag":
|
||||
_ = convert.ConvertAssign(&slave.Lag, propArr[1])
|
||||
}
|
||||
}
|
||||
slaveList = append(slaveList, slave)
|
||||
}
|
||||
return slaveList
|
||||
}
|
||||
|
||||
// GetCPUInfo 获取cpu信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:24 下午 2021/11/27
|
||||
func GetCPUInfo(client *redis.Client) (*CPU, error) {
|
||||
var result CPU
|
||||
if err := infoToStruct(client, "cpu", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetCommandStats 命令状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:27 下午 2021/11/27
|
||||
func GetCommandStats(client *redis.Client) (*Stats, error) {
|
||||
var result Stats
|
||||
if err := infoToStruct(client, "stats", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetCommandInfo 获取命令信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 1:32 下午 2021/11/27
|
||||
func GetCommandInfo(client *redis.Client) ([]CmdStat, error) {
|
||||
var result map[string]string
|
||||
if err := infoToStruct(client, "commandstats", &result); nil != err {
|
||||
return make([]CmdStat, 0), err
|
||||
}
|
||||
cmdList := make([]CmdStat, 0)
|
||||
// 解析数据
|
||||
for cmd, detail := range result {
|
||||
infoArr := strings.Split(detail, ",")
|
||||
if len(infoArr) < 2 {
|
||||
// 去掉开始的描述信息
|
||||
continue
|
||||
}
|
||||
info := CmdStat{
|
||||
Cmd: strings.ReplaceAll(strings.ToLower(cmd), "cmdstat_", ""),
|
||||
Calls: 0,
|
||||
TotalUsedTime: 0,
|
||||
AvgUsedTime: 0,
|
||||
RejectedCalls: 0,
|
||||
FailedCalls: 0,
|
||||
SuccessCalls: 0,
|
||||
}
|
||||
for _, item := range infoArr {
|
||||
itemArr := strings.Split(item, "=")
|
||||
if len(itemArr) != 2 {
|
||||
continue
|
||||
}
|
||||
switch strings.ToLower(itemArr[0]) {
|
||||
case "calls":
|
||||
_ = convert.ConvertAssign(&info.Calls, itemArr[1])
|
||||
case "usec":
|
||||
_ = convert.ConvertAssign(&info.TotalUsedTime, itemArr[1])
|
||||
case "usec_per_call":
|
||||
_ = convert.ConvertAssign(&info.AvgUsedTime, itemArr[1])
|
||||
case "rejected_calls":
|
||||
_ = convert.ConvertAssign(&info.RejectedCalls, itemArr[1])
|
||||
case "failed_calls":
|
||||
_ = convert.ConvertAssign(&info.FailedCalls, itemArr[1])
|
||||
}
|
||||
}
|
||||
info.SuccessCalls = info.Calls - info.FailedCalls - info.RejectedCalls
|
||||
cmdList = append(cmdList, info)
|
||||
}
|
||||
return cmdList, nil
|
||||
}
|
||||
|
||||
// GetKeyspace 获取 keyspace 信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:44 下午 2021/11/27
|
||||
func GetKeyspace(client *redis.Client) ([]DB, error) {
|
||||
var result map[string]string
|
||||
if err := infoToStruct(client, "keyspace", &result); nil != err {
|
||||
return make([]DB, 0), err
|
||||
}
|
||||
dbList := make([]DB, 0)
|
||||
for dbName, item := range result {
|
||||
itemArr := strings.Split(item, ",")
|
||||
if len(itemArr) < 3 {
|
||||
continue
|
||||
}
|
||||
dbInfo := DB{
|
||||
Name: dbName,
|
||||
Keys: 0,
|
||||
Expires: 0,
|
||||
AvgTTL: 0,
|
||||
}
|
||||
for _, kv := range itemArr {
|
||||
kvArr := strings.Split(kv, "=")
|
||||
if len(kvArr) != 2 {
|
||||
continue
|
||||
}
|
||||
switch strings.ToLower(kvArr[0]) {
|
||||
case "keys":
|
||||
_ = convert.ConvertAssign(&dbInfo.Keys, kvArr[1])
|
||||
case "expires":
|
||||
_ = convert.ConvertAssign(&dbInfo.Expires, kvArr[1])
|
||||
case "avg_ttl":
|
||||
_ = convert.ConvertAssign(&dbInfo.AvgTTL, kvArr[1])
|
||||
}
|
||||
}
|
||||
dbList = append(dbList, dbInfo)
|
||||
}
|
||||
return dbList, nil
|
||||
}
|
||||
|
||||
// GetCluster 获取 cluster 信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:30 下午 2021/11/27
|
||||
func GetCluster(client *redis.Client) (*Cluster, error) {
|
||||
var result Cluster
|
||||
if err := infoToStruct(client, "cluster", &result); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetErrorStats 获取错误状态信息
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:35 下午 2021/11/27
|
||||
func GetErrorStats(client *redis.Client) ([]Error, error) {
|
||||
var result map[string]string
|
||||
if err := infoToStruct(client, "errorstats", &result); nil != err {
|
||||
return make([]Error, 0), err
|
||||
}
|
||||
|
||||
errList := make([]Error, 0)
|
||||
for errType, item := range result {
|
||||
itemArr := strings.Split(item, "=")
|
||||
if len(itemArr) != 2 {
|
||||
continue
|
||||
}
|
||||
errInfo := Error{
|
||||
Type: strings.ReplaceAll(errType, "errorstat_", ""),
|
||||
Count: 0,
|
||||
}
|
||||
_ = convert.ConvertAssign(&errInfo.Count, itemArr[1])
|
||||
errList = append(errList, errInfo)
|
||||
}
|
||||
return errList, nil
|
||||
}
|
||||
|
||||
// infoToStruct 读取到的数据,解析到结构体
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:28 下午 2021/11/27
|
||||
func infoToStruct(client *redis.Client, module string, receiver interface{}) error {
|
||||
data := client.Info(context.Background(), module).String()
|
||||
// yaml 文件规范要求, key: val , 注意 : 的后面有空格
|
||||
data = strings.ReplaceAll(data, ":", ": ")
|
||||
return yml.Unmarshal([]byte(data), receiver)
|
||||
}
|
@ -42,12 +42,6 @@ func TestCommandProxy(t *testing.T) {
|
||||
panic(err.Error())
|
||||
}
|
||||
r, cmdErr := instance.CommandProxy(nil, "test_redis", "set", "command_proxy", "hello world")
|
||||
c, _ := instance.GetRedisClient("test_redis")
|
||||
fmt.Println(GetRedisServerInfo(c.Instance))
|
||||
fmt.Println(GetCommandInfo(c.Instance))
|
||||
fmt.Println(GetKeyspace(c.Instance))
|
||||
fmt.Println(GetCluster(c.Instance))
|
||||
fmt.Println(GetErrorStats(c.Instance))
|
||||
assert.Nil(t, cmdErr, "命令执行成功")
|
||||
assert.Equal(t, "OK", fmt.Sprintf("%v", r))
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
// Package tile38 ...
|
||||
//
|
||||
// Description : tile38 ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-18 3:45 下午
|
||||
package tile38
|
@ -1,29 +0,0 @@
|
||||
// Package oauth ...
|
||||
//
|
||||
// Description : oauth ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022/01/17 12:20 AM
|
||||
package oauth
|
||||
|
||||
// Config OAuth相关配置
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:20 AM
|
||||
type Config struct {
|
||||
ClientID string `json:"client_id"` // 授权的client id
|
||||
ClientSecret string `json:"client_secret"` // 授权的client_secret
|
||||
CallbackURL string `json:"callback_url"` // 授权后携带code回调的地址
|
||||
Domain string `json:"domain"` // 服务器域名
|
||||
AuthorizationPageURI string `json:"authorization_page_uri"` // 授权页面URI
|
||||
GetAccessTokenURI string `json:"get_access_token_uri"` // 获取access token地址
|
||||
ValidateAccessTokenURI string `json:"validate_access_token_uri"` // 验证access_token地址
|
||||
AccessTokenKey string `json:"access_token_key"` // 验证access token时的key
|
||||
UseAuthorization bool `json:"use_authorization"` // 是否使用header中的Authorization
|
||||
FormatAccessTokenFunc FormatAccessTokenFunc `json:"format_access_token_func"` // 格式化token的函数
|
||||
}
|
||||
|
||||
// FormatAccessTokenFunc 格式化token
|
||||
type FormatAccessTokenFunc func(token string) string
|
128
oauth/oauth.go
128
oauth/oauth.go
@ -1,128 +0,0 @@
|
||||
// Package oauth ...
|
||||
//
|
||||
// Description : oauth ...
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 2022/01/17 12:18 AM
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ddliu/go-httpclient"
|
||||
)
|
||||
|
||||
// NewOAuth 获取OAuth实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:19 AM
|
||||
func NewOAuth(cfg Config) *OAuth {
|
||||
return &OAuth{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// OAuth 管理
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:19 AM
|
||||
type OAuth struct {
|
||||
cfg Config
|
||||
}
|
||||
|
||||
// GetAuthorizationPageURL 获取授权页面的URL
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:33 AM
|
||||
func (o *OAuth) GetAuthorizationPageURL(scope string, responseType string) string {
|
||||
return fmt.Sprintf(
|
||||
"%s%s?client_id=%s&redirect_uri=%s&scope=%s&response_type=%s",
|
||||
o.cfg.Domain,
|
||||
o.cfg.AuthorizationPageURI,
|
||||
o.cfg.ClientID,
|
||||
url.QueryEscape(o.cfg.CallbackURL),
|
||||
scope,
|
||||
responseType,
|
||||
)
|
||||
}
|
||||
|
||||
// ApplyAccessTokenByCode 通过code申请授权token
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:35 AM
|
||||
func (o *OAuth) ApplyAccessTokenByCode(code string, receiver interface{}) error {
|
||||
// OAuth 授权回调
|
||||
parameter := map[string]string{
|
||||
"code": code,
|
||||
"client_id": o.cfg.ClientID,
|
||||
"client_secret": o.cfg.ClientSecret,
|
||||
"grant_type": "authorization_code",
|
||||
}
|
||||
client := httpclient.NewHttpClient()
|
||||
client.WithHeader("Accept", "application/json")
|
||||
resp, err := client.Post(o.cfg.Domain+o.cfg.GetAccessTokenURI+"?grant_type=authorization_code", parameter)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("【%v】%v", resp.StatusCode, resp.Status)
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if nil != err {
|
||||
return errors.New("读取响应体失败: " + err.Error())
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(body))
|
||||
decoder.UseNumber()
|
||||
return decoder.Decode(receiver)
|
||||
}
|
||||
|
||||
// ValidateAccessToken 验证授权token
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:43 AM
|
||||
func (o *OAuth) ValidateAccessToken(token string, receiver interface{}) error {
|
||||
if nil != o.cfg.FormatAccessTokenFunc {
|
||||
token = o.cfg.FormatAccessTokenFunc(token)
|
||||
}
|
||||
parameter := make(map[string]string)
|
||||
client := httpclient.NewHttpClient()
|
||||
client.WithHeader("Accept", "application/json")
|
||||
if o.cfg.UseAuthorization {
|
||||
client.WithHeader("Authorization", "token "+token)
|
||||
} else {
|
||||
parameter[o.cfg.AccessTokenKey] = token
|
||||
}
|
||||
resp, err := client.Get("https://git.zhangdeman.cn/api/v1/user?grant_type=authorization_code", parameter)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if nil != err {
|
||||
return errors.New("读取响应体失败 : " + err.Error())
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(body))
|
||||
decoder.UseNumber()
|
||||
return decoder.Decode(receiver)
|
||||
}
|
||||
|
||||
// GetUserDetailByToken 根据 token 获取用户详情
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/17 12:55 AM
|
||||
func (o *OAuth) GetUserDetailByToken(token string, receiver interface{}) error {
|
||||
return o.ValidateAccessToken(token, receiver)
|
||||
}
|
@ -8,11 +8,13 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -22,30 +24,72 @@ import (
|
||||
//
|
||||
// Date : 2:08 下午 2021/8/6
|
||||
func Forward(rw http.ResponseWriter, req *http.Request, serverConfig *Server) {
|
||||
fmt.Printf("Received request %s %s %s\n", req.Method, req.Host, req.RemoteAddr)
|
||||
|
||||
if !strings.HasPrefix(serverConfig.URI, "/") {
|
||||
serverConfig.URI = "/" + serverConfig.URI
|
||||
transport := http.DefaultTransport
|
||||
|
||||
// step 1
|
||||
outReq := new(http.Request)
|
||||
*outReq = *req // this only does shallow copies of maps
|
||||
|
||||
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
|
||||
if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
|
||||
clientIP = strings.Join(prior, ", ") + ", " + clientIP
|
||||
}
|
||||
outReq.Header.Set("X-Forwarded-For", clientIP)
|
||||
}
|
||||
// 请求重写方法
|
||||
director := func(req *http.Request) {
|
||||
req.URL.Scheme = serverConfig.Scheme
|
||||
// req.URL.Host = projectDetail.GetProjectDetail().Domain + ":" + fmt.Sprintf("%v", projectDetail.GetProjectDetail().Port)
|
||||
// req.Host = projectDetail.GetProjectDetail().Domain + ":" + fmt.Sprintf("%v", projectDetail.GetProjectDetail().Port)
|
||||
req.Host = serverConfig.Host
|
||||
req.URL.Host = serverConfig.Host
|
||||
req.URL.Path = serverConfig.URI
|
||||
req.RequestURI = serverConfig.URI
|
||||
// 写入重写的请求Header
|
||||
for k, v := range serverConfig.RewriteRequestHeader {
|
||||
req.Header.Set(k, v)
|
||||
|
||||
// 写入重写的请求Header
|
||||
for k, v := range serverConfig.RewriteRequestHeader {
|
||||
outReq.Header.Set(k, v)
|
||||
}
|
||||
|
||||
// 重写请求地址
|
||||
outReq.Host = serverConfig.Host
|
||||
outReq.URL.Path = serverConfig.URI
|
||||
outReq.URL.Scheme = serverConfig.Scheme
|
||||
outReq.URL.Host = serverConfig.Host
|
||||
|
||||
// step 2
|
||||
res, err := transport.RoundTrip(outReq)
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
|
||||
// step 3
|
||||
for key, value := range res.Header {
|
||||
for _, v := range value {
|
||||
if strings.ToLower(key) == "content-encoding" {
|
||||
continue
|
||||
}
|
||||
rw.Header().Add(key, v)
|
||||
}
|
||||
}
|
||||
// TODO : 重写响应数据
|
||||
modifyResponseFunc := func(rep *http.Response) error {
|
||||
return nil
|
||||
|
||||
rw.WriteHeader(res.StatusCode)
|
||||
|
||||
// 重写请求header
|
||||
for k, v := range serverConfig.RewriteResponseHeader {
|
||||
rw.Header().Set(k, v)
|
||||
}
|
||||
p := &httputil.ReverseProxy{Director: director, ModifyResponse: modifyResponseFunc}
|
||||
p.ServeHTTP(rw, req)
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
// 重写响应数据
|
||||
if !strings.Contains(strings.ToLower(res.Header.Get("Content-Type")), "application/json") || nil == serverConfig.RewriteResponseData || len(serverConfig.RewriteResponseData) == 0 {
|
||||
_, _ = io.Copy(rw, res.Body)
|
||||
return
|
||||
}
|
||||
var (
|
||||
responseData []byte
|
||||
)
|
||||
|
||||
responseData, err = getResponseData(res)
|
||||
fmt.Println(string(responseData), err)
|
||||
|
||||
bytesBuffer := bytes.NewReader([]byte(`{"data":{"permission":true}}`))
|
||||
_, _ = io.Copy(rw, bytesBuffer)
|
||||
}
|
||||
|
||||
// getResultCompressType 获取返回结果的压缩方式
|
||||
|
@ -1,25 +0,0 @@
|
||||
// Package system...
|
||||
//
|
||||
// Description : system...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-12 5:58 下午
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGetCPUInfo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:58 下午 2021/10/12
|
||||
func TestGetCPUInfo(t *testing.T) {
|
||||
r, _ := GetCPUInfo()
|
||||
byteData, _ := json.Marshal(r)
|
||||
fmt.Println(string(byteData))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Package system...
|
||||
//
|
||||
// Description : system...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-12 9:04 下午
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGetDiskInfo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 9:04 下午 2021/10/12
|
||||
func TestGetDiskInfo(t *testing.T) {
|
||||
r, _ := GetDiskInfo()
|
||||
byteData, _ := json.Marshal(r)
|
||||
fmt.Println(string(byteData))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Package system...
|
||||
//
|
||||
// Description : system...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-12 7:58 下午
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGetHostInfo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:59 下午 2021/10/12
|
||||
func TestGetHostInfo(t *testing.T) {
|
||||
r, _ := GetHostInfo()
|
||||
byteData, _ := json.Marshal(r)
|
||||
fmt.Println(string(byteData))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Package system...
|
||||
//
|
||||
// Description : system...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-12 7:09 下午
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGetMemoryInfo ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:09 下午 2021/10/12
|
||||
func TestGetMemoryInfo(t *testing.T) {
|
||||
r, _ := GetMemoryInfo()
|
||||
byteData, _ := json.Marshal(r)
|
||||
fmt.Println(string(byteData))
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,301 +0,0 @@
|
||||
// Package json2go...
|
||||
//
|
||||
// Description : json2go...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-09 4:21 下午
|
||||
package json2go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
testJSON := `{
|
||||
"name": "zhang",
|
||||
"test": {
|
||||
"name": "aa",
|
||||
"age": 18,
|
||||
"third": {"a":"1", "b":"like"},
|
||||
"result": true,
|
||||
"result_fail":false
|
||||
},
|
||||
"list": [1,2,3,4],
|
||||
"list1": [2.2, 3, 4, 5],
|
||||
"list_object":[{"name":"zhang"}, {"age": 18}]
|
||||
}`
|
||||
testJSON = `{
|
||||
"ref": "refs/heads/master",
|
||||
"before": "4c8219477db1e93e5540c9af4889f2633a9ca9e9",
|
||||
"after": "5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"compare_url": "https://git.zhangdeman.cn/zhangdeman/manager-job/compare/4c8219477db1e93e5540c9af4889f2633a9ca9e9...5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"commits": [
|
||||
{
|
||||
"id": "5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"message": "更新文案\n",
|
||||
"url": "https://git.zhangdeman.cn/zhangdeman/manager-job/commit/5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"author": {
|
||||
"name": "白茶清欢",
|
||||
"email": "go_developer@163.com",
|
||||
"username": "zhangdeman"
|
||||
},
|
||||
"committer": {
|
||||
"name": "白茶清欢",
|
||||
"email": "go_developer@163.com",
|
||||
"username": "zhangdeman"
|
||||
},
|
||||
"verification": null,
|
||||
"timestamp": "2021-11-11T17:54:40+08:00",
|
||||
"added": [],
|
||||
"removed": [],
|
||||
"modified": [
|
||||
"publish_admin.sh"
|
||||
]
|
||||
}
|
||||
],
|
||||
"head_commit": {
|
||||
"id": "5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"message": "更新文案\n",
|
||||
"url": "https://git.zhangdeman.cn/zhangdeman/manager-job/commit/5888c985a9afd9f1b25807fade69c53938aef485",
|
||||
"author": {
|
||||
"name": "白茶清欢",
|
||||
"email": "go_developer@163.com",
|
||||
"username": "zhangdeman"
|
||||
},
|
||||
"committer": {
|
||||
"name": "白茶清欢",
|
||||
"email": "go_developer@163.com",
|
||||
"username": "zhangdeman"
|
||||
},
|
||||
"verification": null,
|
||||
"timestamp": "2021-11-11T17:54:40+08:00",
|
||||
"added": [],
|
||||
"removed": [],
|
||||
"modified": [
|
||||
"publish_admin.sh"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"id": 24,
|
||||
"owner": {"id":1,"login":"zhangdeman","full_name":"","email":"go_developer@163.com","avatar_url":"https://git.zhangdeman.cn/user/avatar/zhangdeman/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2021-05-04T12:58:50+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"zhangdeman"},
|
||||
"name": "manager-job",
|
||||
"full_name": "zhangdeman/manager-job",
|
||||
"description": "各种管理JOB",
|
||||
"empty": false,
|
||||
"private": false,
|
||||
"fork": false,
|
||||
"template": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 24,
|
||||
"html_url": "https://git.zhangdeman.cn/zhangdeman/manager-job",
|
||||
"ssh_url": "www@git.zhangdeman.cn:zhangdeman/manager-job.git",
|
||||
"clone_url": "https://git.zhangdeman.cn/zhangdeman/manager-job.git",
|
||||
"original_url": "",
|
||||
"website": "",
|
||||
"stars_count": 0,
|
||||
"forks_count": 0,
|
||||
"watchers_count": 1,
|
||||
"open_issues_count": 0,
|
||||
"open_pr_counter": 0,
|
||||
"release_counter": 0,
|
||||
"default_branch": "master",
|
||||
"archived": false,
|
||||
"created_at": "2021-11-11T16:54:10+08:00",
|
||||
"updated_at": "2021-11-11T17:02:22+08:00",
|
||||
"permissions": {
|
||||
"admin": true,
|
||||
"push": true,
|
||||
"pull": true
|
||||
},
|
||||
"has_issues": true,
|
||||
"internal_tracker": {
|
||||
"enable_time_tracker": false,
|
||||
"allow_only_contributors_to_track_time": true,
|
||||
"enable_issue_dependencies": true
|
||||
},
|
||||
"has_wiki": true,
|
||||
"has_pull_requests": true,
|
||||
"has_projects": true,
|
||||
"ignore_whitespace_conflicts": false,
|
||||
"allow_merge_commits": true,
|
||||
"allow_rebase": true,
|
||||
"allow_rebase_explicit": true,
|
||||
"allow_squash_merge": true,
|
||||
"default_merge_style": "merge",
|
||||
"avatar_url": "",
|
||||
"internal": false,
|
||||
"mirror_interval": ""
|
||||
},
|
||||
"pusher": {"id":1,"login":"zhangdeman","full_name":"","email":"go_developer@163.com","avatar_url":"https://git.zhangdeman.cn/user/avatar/zhangdeman/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2021-05-04T12:58:50+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"zhangdeman"},
|
||||
"sender": {"id":1,"login":"zhangdeman","full_name":"","email":"go_developer@163.com","avatar_url":"https://git.zhangdeman.cn/user/avatar/zhangdeman/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2021-05-04T12:58:50+08:00","restricted":false,"active":false,"prohibit_login":false,"location":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"zhangdeman"}
|
||||
}
|
||||
`
|
||||
fmt.Println(NewJSON2GO("DemoJSON").Parse(testJSON))
|
||||
}
|
||||
|
||||
type DemoJSON struct {
|
||||
Repository struct {
|
||||
Mirror bool `json:"mirror"`
|
||||
OriginalUrl string `json:"original_url"`
|
||||
StarsCount int64 `json:"stars_count"`
|
||||
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||
FullName string `json:"full_name"`
|
||||
Fork bool `json:"fork"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Internal bool `json:"internal"`
|
||||
AllowRebaseExplicit bool `json:"allow_rebase_explicit"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
CloneUrl string `json:"clone_url"`
|
||||
WatchersCount int64 `json:"watchers_count"`
|
||||
OpenIssuesCount int64 `json:"open_issues_count"`
|
||||
ReleaseCounter int64 `json:"release_counter"`
|
||||
InternalTracker struct {
|
||||
EnableTimeTracker bool `json:"enable_time_tracker"`
|
||||
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
|
||||
EnableIssueDependencies bool `json:"enable_issue_dependencies"`
|
||||
} `json:"internal_tracker"`
|
||||
Name string `json:"name"`
|
||||
Empty bool `json:"empty"`
|
||||
SshUrl string `json:"ssh_url"`
|
||||
ForksCount int64 `json:"forks_count"`
|
||||
Permissions struct {
|
||||
Pull bool `json:"pull"`
|
||||
Admin bool `json:"admin"`
|
||||
Push bool `json:"push"`
|
||||
} `json:"permissions"`
|
||||
Private bool `json:"private"`
|
||||
Size int64 `json:"size"`
|
||||
HasWiki bool `json:"has_wiki"`
|
||||
HasProjects bool `json:"has_projects"`
|
||||
AllowMergeCommits bool `json:"allow_merge_commits"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
Id int64 `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Website string `json:"website"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
HasPullRequests bool `json:"has_pull_requests"`
|
||||
Parent map[string]interface{} `json:"parent"`
|
||||
OpenPrCounter int64 `json:"open_pr_counter"`
|
||||
HasIssues bool `json:"has_issues"`
|
||||
AllowRebase bool `json:"allow_rebase"`
|
||||
AllowSquashMerge bool `json:"allow_squash_merge"`
|
||||
Owner 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"`
|
||||
StarredReposCount int64 `json:"starred_repos_count"`
|
||||
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"`
|
||||
Id int64 `json:"id"`
|
||||
Language string `json:"language"`
|
||||
} `json:"owner"`
|
||||
Template bool `json:"template"`
|
||||
HtmlUrl string `json:"html_url"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Archived bool `json:"archived"`
|
||||
DefaultMergeStyle string `json:"default_merge_style"`
|
||||
} `json:"repository"`
|
||||
Sender struct {
|
||||
Created string `json:"created"`
|
||||
Website string `json:"website"`
|
||||
FollowingCount int64 `json:"following_count"`
|
||||
StarredReposCount int64 `json:"starred_repos_count"`
|
||||
FullName string `json:"full_name"`
|
||||
Language string `json:"language"`
|
||||
LastLogin string `json:"last_login"`
|
||||
Visibility string `json:"visibility"`
|
||||
FollowersCount int64 `json:"followers_count"`
|
||||
Username string `json:"username"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
Active bool `json:"active"`
|
||||
Location string `json:"location"`
|
||||
Restricted bool `json:"restricted"`
|
||||
Description string `json:"description"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
ProhibitLogin bool `json:"prohibit_login"`
|
||||
Id int64 `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Email string `json:"email"`
|
||||
} `json:"sender"`
|
||||
Ref string `json:"ref"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
HeadCommit struct {
|
||||
Message string `json:"message"`
|
||||
Url string `json:"url"`
|
||||
Author struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
} `json:"author"`
|
||||
Verification map[string]interface{} `json:"verification"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Id string `json:"id"`
|
||||
Committer struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
} `json:"committer"`
|
||||
Added []interface{} `json:"added"`
|
||||
Removed []interface{} `json:"removed"`
|
||||
Modified []string `json:"modified"`
|
||||
} `json:"head_commit"`
|
||||
CompareUrl string `json:"compare_url"`
|
||||
Commits []struct {
|
||||
Url string `json:"url"`
|
||||
Author struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
} `json:"author"`
|
||||
Committer struct {
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"committer"`
|
||||
Verification map[string]interface{} `json:"verification"`
|
||||
Removed []interface{} `json:"removed"`
|
||||
Id string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
Modified []string `json:"modified"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Added []interface{} `json:"added"`
|
||||
} `json:"commits"`
|
||||
Pusher struct {
|
||||
Language string `json:"language"`
|
||||
Website string `json:"website"`
|
||||
Id int64 `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Active bool `json:"active"`
|
||||
Description string `json:"description"`
|
||||
Visibility string `json:"visibility"`
|
||||
Login string `json:"login"`
|
||||
Restricted bool `json:"restricted"`
|
||||
Location string `json:"location"`
|
||||
StarredReposCount int64 `json:"starred_repos_count"`
|
||||
Username string `json:"username"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
ProhibitLogin bool `json:"prohibit_login"`
|
||||
LastLogin string `json:"last_login"`
|
||||
Created string `json:"created"`
|
||||
FollowersCount int64 `json:"followers_count"`
|
||||
FollowingCount int64 `json:"following_count"`
|
||||
FullName string `json:"full_name"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
} `json:"pusher"`
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// Package sql2go...
|
||||
//
|
||||
// Description : sql2go...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-17 11:46 上午
|
||||
package sql2go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGenerateDao ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:05 下午 2021/11/17
|
||||
func TestGenerateDao(t *testing.T) {
|
||||
sql := "CREATE TABLE `app` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',\n `code` varchar(128) NOT NULL DEFAULT '' COMMENT '分配的app_code',\n `secret` varchar(64) NOT NULL DEFAULT '' COMMENT '分配的私钥',\n `status` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '当前状态 o - 初始化 1- 使用中 2 - 禁用 3 - 删除',\n `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述信息',\n `apply_user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '申请人姓名',\n `apply_user_contact` varchar(128) NOT NULL DEFAULT '' COMMENT '申请人联系方式',\n `create_user_id` varchar(128) NOT NULL DEFAULT '' COMMENT '创建人ID',\n `modify_user_id` varchar(128) NOT NULL DEFAULT '' COMMENT '修改人ID',\n PRIMARY KEY (`id`),\n UNIQUE KEY `uniq_code` (`code`)\n) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COMMENT='APP信息表'"
|
||||
fmt.Println(GenerateDao(sql, "sql2go"))
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
// Package dao ...
|
||||
//
|
||||
// Description : dao ...
|
||||
package sql2go
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// App 数据库表的数据结构
|
||||
type App struct {
|
||||
ID int64 `json:"id" gorm:"column:id;default:;NOT NULL"` // id 主键ID
|
||||
Code string `json:"code" gorm:"column:code;default:;NOT NULL"` // code 分配的app_code
|
||||
Secret string `json:"secret" gorm:"column:secret;default:;NOT NULL"` // secret 分配的私钥
|
||||
Status int `json:"status" gorm:"column:status;default:0;NOT NULL"` // status 当前状态 o - 初始化 1- 使用中 2 - 禁用 3 - 删除
|
||||
Description string `json:"description" gorm:"column:description;default:;NOT NULL"` // description 描述信息
|
||||
ApplyUserName string `json:"apply_user_name" gorm:"column:apply_user_name;default:;NOT NULL"` // apply_user_name 申请人姓名
|
||||
ApplyUserContact string `json:"apply_user_contact" gorm:"column:apply_user_contact;default:;NOT NULL"` // apply_user_contact 申请人联系方式
|
||||
CreateUserID string `json:"create_user_id" gorm:"column:create_user_id;default:;NOT NULL"` // create_user_id 创建人ID
|
||||
ModifyUserID string `json:"modify_user_id" gorm:"column:modify_user_id;default:;NOT NULL"` // modify_user_id 修改人ID
|
||||
}
|
||||
|
||||
// NewAppDao 获取DAO实例
|
||||
func NewAppDao() *AppDao {
|
||||
return &AppDao{
|
||||
table: "app",
|
||||
}
|
||||
}
|
||||
|
||||
// AppDao sql2go tool generate
|
||||
type AppDao struct {
|
||||
table string
|
||||
}
|
||||
|
||||
// GetDetailByID 根据主键ID获取详情
|
||||
func (ad *AppDao) GetDetailByID(dbInstance *gorm.DB, ID int64) (*App, error) {
|
||||
var (
|
||||
err error
|
||||
detail App
|
||||
)
|
||||
if err = dbInstance.Table(ad.table).Where("{PRIMARY_KEY_FIELD} = ?", ID).Limit(1).First(&detail).Error; nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return &detail, nil
|
||||
}
|
||||
|
||||
// GetList 获取数据列表
|
||||
func (ad *AppDao) GetList(dbInstance *gorm.DB, condition map[string]interface{}, limit int, offset int) ([]App, error) {
|
||||
if nil == condition {
|
||||
condition = make(map[string]interface{})
|
||||
}
|
||||
var (
|
||||
err error
|
||||
list []App
|
||||
)
|
||||
if err = dbInstance.Table(ad.table).Where(condition).Limit(limit).Offset(offset).Find(&list).Error; nil != err {
|
||||
return make([]App, 0), err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Create 创建数据
|
||||
func (ad *AppDao) Create(dbInstance *gorm.DB, data *App) error {
|
||||
if nil == data {
|
||||
return errors.New("data is nil")
|
||||
}
|
||||
return dbInstance.Table(ad.table).Create(data).Error
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
package sql2go
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
@ -21,47 +20,23 @@ 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, *BasicTableInfo, error) {
|
||||
func ParseCreateTableSql(sql string) (string, error) {
|
||||
var (
|
||||
stmt sqlparser.Statement
|
||||
err error
|
||||
basic *BasicTableInfo
|
||||
stmt sqlparser.Statement
|
||||
err error
|
||||
)
|
||||
basic = &BasicTableInfo{
|
||||
TableName: "",
|
||||
ModelStruct: "",
|
||||
PrimaryField: "ID",
|
||||
PrimaryFieldType: "",
|
||||
}
|
||||
sql = strings.ReplaceAll(strings.ReplaceAll(sql, "CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP"), "current_timestamp()", "CURRENT_TIMESTAMP")
|
||||
sql = strings.ReplaceAll(strings.ToUpper(sql), "CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP")
|
||||
if stmt, err = sqlparser.ParseStrictDDL(sql); nil != err {
|
||||
return "", nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, ok := stmt.(*sqlparser.DDL)
|
||||
if !ok {
|
||||
return "", nil, errors.New("input sql is not ddl")
|
||||
}
|
||||
basic.TableName = sqlparser.String(r.NewName)
|
||||
basic.ModelStruct = util.SnakeCaseToCamel(basic.TableName)
|
||||
structResult := "type " + basic.ModelStruct + " struct { \n"
|
||||
r := stmt.(*sqlparser.DDL)
|
||||
structResult := "type " + util.SnakeCaseToCamel(sqlparser.String(r.NewName)) + " struct { \n"
|
||||
|
||||
for _, item := range r.TableSpec.Columns {
|
||||
data := map[string]string{
|
||||
@ -72,9 +47,6 @@ func ParseCreateTableSql(sql string) (string, *BasicTableInfo, 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"
|
||||
}
|
||||
@ -88,5 +60,5 @@ func ParseCreateTableSql(sql string) (string, *BasicTableInfo, error) {
|
||||
structResult += val + "\n"
|
||||
}
|
||||
structResult = structResult + "}"
|
||||
return structResult, basic, nil
|
||||
return structResult, nil
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
// Package sql2go...
|
||||
//
|
||||
// Description : sql2go...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-10-25 5:02 下午
|
||||
package sql2go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseSql(t *testing.T) {
|
||||
sql := "CREATE TABLE `app` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',\n `code` varchar(128) NOT NULL DEFAULT '' COMMENT '分配的app_code',\n `secret` varchar(64) NOT NULL DEFAULT '' COMMENT '分配的私钥',\n `status` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '当前状态 o - 初始化 1- 使用中 2 - 禁用 3 - 删除',\n `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述信息',\n `apply_user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '申请人姓名',\n `apply_user_contact` varchar(128) NOT NULL DEFAULT '' COMMENT '申请人联系方式',\n `create_user_id` varchar(128) NOT NULL DEFAULT '' COMMENT '创建人ID',\n `modify_user_id` varchar(128) NOT NULL DEFAULT '' COMMENT '修改人ID',\n PRIMARY KEY (`id`),\n UNIQUE KEY `uniq_code` (`code`)\n) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COMMENT='APP信息表'"
|
||||
fmt.Println(ParseCreateTableSql(sql))
|
||||
}
|
26
util/ip.go
26
util/ip.go
@ -7,10 +7,7 @@
|
||||
// Date : 2021-03-09 5:56 下午
|
||||
package util
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
import "net"
|
||||
|
||||
// GetHostIP 获取本机IP地址
|
||||
//
|
||||
@ -30,24 +27,3 @@ 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,10 +10,7 @@ package util
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// JSONUnmarshalWithNumber 解析json
|
||||
@ -37,55 +34,3 @@ 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("")
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Package util...
|
||||
//
|
||||
// Description : util...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-05 6:10 下午
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestJSONMarshal ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:12 下午 2021/11/5
|
||||
func TestJSONMarshal(t *testing.T) {
|
||||
data := `{"name":"zhangdeman", "age":18, "height": 180}`
|
||||
JSONConsoleOutput(data)
|
||||
}
|
209
util/map.go
209
util/map.go
@ -1,209 +0,0 @@
|
||||
// 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,9 +54,6 @@ 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' {
|
||||
@ -71,11 +68,6 @@ 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
89
util/url.go
@ -1,89 +0,0 @@
|
||||
// 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()
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// Package util...
|
||||
//
|
||||
// Description : util...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-04 2:58 下午
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestBuildQueryURL ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:04 下午 2021/11/4
|
||||
func TestBuildQueryURL(t *testing.T) {
|
||||
url := "https://ww.baidu.com/api/detail"
|
||||
parameter := map[string]string{
|
||||
"name": "zhang",
|
||||
"age": "18",
|
||||
}
|
||||
fmt.Println(BuildQueryURL(url, parameter))
|
||||
url = "https://ww.baidu.com/api/detail?tag=1"
|
||||
fmt.Println(BuildQueryURL(url, parameter))
|
||||
}
|
||||
|
||||
// TestURLDecode ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:04 下午 2021/11/4
|
||||
func TestURLDecode(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestURLEncode ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:05 下午 2021/11/4
|
||||
func TestURLEncode(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestURLParse 测试URL解析
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:00 下午 2021/11/4
|
||||
func TestURLParse(t *testing.T) {
|
||||
inputURL := "https://www.baidu.com/api/detail?a=1&b=2&a=3&d=qwe"
|
||||
r, _ := URLParse(inputURL)
|
||||
byteData, _ := json.Marshal(r)
|
||||
fmt.Println(string(byteData))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user