Compare commits
21 Commits
e8ab043be7
...
feature/ec
Author | SHA1 | Date | |
---|---|---|---|
391e47fe33 | |||
fa426ae90c | |||
39e3cdef91 | |||
ad8c3dc47d | |||
42282e2001 | |||
376f3dfb23 | |||
275e52a108 | |||
ffccdeffd4 | |||
30059c0341 | |||
cf210a4514 | |||
a9a4287650 | |||
802c795914 | |||
73f4af74f9 | |||
affaca969e | |||
168bb99c65 | |||
5e136c1749 | |||
0701313fa7 | |||
62cdd3570a | |||
daab8f3bd5 | |||
28d9566e07 | |||
ca74db4587 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.xlsx
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
30
balance/abstract.go
Normal file
30
balance/abstract.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Package balance...
|
||||
//
|
||||
// Description : balance...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-22 4:45 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// IBalance 负载算法接口约束
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:45 下午 2021/11/22
|
||||
type IBalance interface {
|
||||
// GetServerNode 获取一个服务器节点
|
||||
GetServerNode(req *http.Request) (*define.ServerNode, error)
|
||||
// AddServerNode 新增一个服务器节点
|
||||
AddServerNode(node *define.ServerNode) error
|
||||
// Remove 移除一个节点
|
||||
Remove(hostIP string, port int, force bool)
|
||||
// GetServerNodeList 获取服务节点列表
|
||||
GetServerNodeList() []*define.ServerNode
|
||||
}
|
@ -7,7 +7,12 @@
|
||||
// Date : 2021-10-19 2:26 下午
|
||||
package balance
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// base ...
|
||||
//
|
||||
@ -16,6 +21,7 @@ import "sync"
|
||||
// Date : 2:26 下午 2021/10/19
|
||||
type base struct {
|
||||
lock *sync.RWMutex
|
||||
severList []*define.ServerNode
|
||||
}
|
||||
|
||||
// Lock ...
|
||||
@ -53,3 +59,53 @@ func (b *base) RLock() {
|
||||
func (b *base) RUnlock() {
|
||||
b.lock.RUnlock()
|
||||
}
|
||||
|
||||
// AddServerNode 新添加一个服务器节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:07 下午 2021/10/20
|
||||
func (b *base) AddServerNode(node *define.ServerNode) error {
|
||||
if len(node.HostIP) == 0 || node.Port <= 0 {
|
||||
return errors.New("host ip or port is invalid")
|
||||
}
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
for _, item := range b.severList {
|
||||
if item.HostIP == node.HostIP && item.Port == node.Port {
|
||||
return errors.New("host config is already exist")
|
||||
}
|
||||
}
|
||||
b.severList = append(b.severList, node)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:19 下午 2021/10/20
|
||||
func (b *base) Remove(hostIP string, port int, force bool) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
tmpServerNode := make([]*define.ServerNode, 0)
|
||||
for _, item := range b.severList {
|
||||
if item.HostIP == hostIP && item.Port == port {
|
||||
if force {
|
||||
continue
|
||||
}
|
||||
item.Status = define.ServerNodeStatusRemove
|
||||
}
|
||||
tmpServerNode = append(tmpServerNode, item)
|
||||
}
|
||||
b.severList = tmpServerNode
|
||||
}
|
||||
|
||||
// GetServerNodeList 获取服务器节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:33 下午 2021/10/20
|
||||
func (b *base) GetServerNodeList() []*define.ServerNode {
|
||||
return b.severList
|
||||
}
|
||||
|
@ -16,5 +16,6 @@ type ServerNode struct {
|
||||
HostIP string `json:"host_ip"` // 机器IP
|
||||
Port int `json:"port"` // 机器端口
|
||||
Status int `json:"status"` // 机器状态
|
||||
Weight int `json:"weight"` // 机器权重
|
||||
Weight float64 `json:"weight"` // 机器权重
|
||||
CurrentWeight float64 `json:"current_weight"` // 当前权重
|
||||
}
|
||||
|
62
balance/ip_hash.go
Normal file
62
balance/ip_hash.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Package balance...
|
||||
//
|
||||
// Description : balance...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-22 4:39 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// NewIPHash ip hash 负载均衡
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:53 下午 2021/11/22
|
||||
func NewIPHash(severList []*define.ServerNode) (IBalance, error) {
|
||||
if nil == severList || len(severList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
return &IPHash{
|
||||
base: base{
|
||||
lock: &sync.RWMutex{},
|
||||
severList: severList,
|
||||
},
|
||||
serverList: severList,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IPHash ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:57 下午 2021/11/22
|
||||
type IPHash struct {
|
||||
base
|
||||
serverList []*define.ServerNode
|
||||
}
|
||||
|
||||
// GetServerNode ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:53 下午 2021/11/22
|
||||
func (ih *IPHash) GetServerNode(req *http.Request) (*define.ServerNode, error) {
|
||||
clintIPHashID := util.GetHashID(util.GetRemoteIp(req))
|
||||
ih.RLock()
|
||||
defer ih.RUnlock()
|
||||
if len(ih.serverList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
return ih.serverList[int(clintIPHashID%uint64(len(ih.serverList)))], nil
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
package balance
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
@ -19,15 +20,15 @@ import (
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:40 下午 2021/10/19
|
||||
func NewPoll(serverList []*define.ServerNode) (*Poll, error) {
|
||||
func NewPoll(serverList []*define.ServerNode) (IBalance, error) {
|
||||
if nil == serverList || len(serverList) == 0 {
|
||||
return nil, errors.New("server list is empty")
|
||||
}
|
||||
return &Poll{
|
||||
base: base{
|
||||
lock: &sync.RWMutex{},
|
||||
severList: serverList,
|
||||
},
|
||||
serverList: serverList,
|
||||
currentServerIndex: 0,
|
||||
}, nil
|
||||
}
|
||||
@ -39,7 +40,6 @@ func NewPoll(serverList []*define.ServerNode) (*Poll, error) {
|
||||
// Date : 12:41 下午 2021/10/19
|
||||
type Poll struct {
|
||||
base
|
||||
serverList []*define.ServerNode
|
||||
currentServerIndex int
|
||||
}
|
||||
|
||||
@ -48,21 +48,18 @@ type Poll struct {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:43 下午 2021/10/19
|
||||
func (p *Poll) GetServerNode() (*define.ServerNode, error) {
|
||||
if len(p.serverList) == 0 {
|
||||
return nil, errors.New("server list is empty")
|
||||
}
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
func (p *Poll) GetServerNode(req *http.Request) (*define.ServerNode, error) {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
var (
|
||||
serverNode *define.ServerNode
|
||||
)
|
||||
// 循环次数
|
||||
loopTimes := 0
|
||||
for loopTimes < len(p.serverList) {
|
||||
for loopTimes < len(p.severList) {
|
||||
loopTimes++
|
||||
p.currentServerIndex = (p.currentServerIndex + 1) % len(p.serverList)
|
||||
if serverNode = p.serverList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal {
|
||||
p.currentServerIndex = (p.currentServerIndex + 1) % len(p.severList)
|
||||
if serverNode = p.severList[p.currentServerIndex]; serverNode.Status != define.ServerNodeStatusNormal {
|
||||
continue
|
||||
}
|
||||
break
|
||||
@ -74,57 +71,3 @@ func (p *Poll) GetServerNode() (*define.ServerNode, error) {
|
||||
|
||||
return serverNode, nil
|
||||
}
|
||||
|
||||
// AddServerNode 新添加一个服务器节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:07 下午 2021/10/20
|
||||
func (p *Poll) AddServerNode(hostIP string, port int) error {
|
||||
if len(hostIP) == 0 || port <= 0 {
|
||||
return errors.New("host ip or port is invalid")
|
||||
}
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
for _, item := range p.serverList {
|
||||
if item.HostIP == hostIP && item.Port == port {
|
||||
return errors.New("host config is already exist")
|
||||
}
|
||||
}
|
||||
p.serverList = append(p.serverList, &define.ServerNode{
|
||||
HostIP: hostIP,
|
||||
Port: port,
|
||||
Status: define.ServerNodeStatusNormal,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:19 下午 2021/10/20
|
||||
func (p *Poll) Remove(hostIP string, port int, force bool) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
tmpServerNode := make([]*define.ServerNode, 0)
|
||||
for _, item := range p.serverList {
|
||||
if item.HostIP == hostIP && item.Port == port {
|
||||
if force {
|
||||
continue
|
||||
}
|
||||
item.Status = define.ServerNodeStatusRemove
|
||||
}
|
||||
tmpServerNode = append(tmpServerNode, item)
|
||||
}
|
||||
p.serverList = tmpServerNode
|
||||
}
|
||||
|
||||
// GetServerNodeList 获取服务器节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:33 下午 2021/10/20
|
||||
func (p *Poll) GetServerNodeList() []*define.ServerNode {
|
||||
return p.serverList
|
||||
}
|
||||
|
59
balance/random.go
Normal file
59
balance/random.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Package balance...
|
||||
//
|
||||
// Description : balance...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-22 6:27 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/util"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// NewRandom ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:29 下午 2021/11/22
|
||||
func NewRandom(severList []*define.ServerNode) (IBalance, error) {
|
||||
if nil == severList || len(severList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
return &Random{
|
||||
base{
|
||||
lock: &sync.RWMutex{},
|
||||
severList: make([]*define.ServerNode, 0),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Random 随机负载均衡
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:27 下午 2021/11/22
|
||||
type Random struct {
|
||||
base
|
||||
}
|
||||
|
||||
// GetServerNode ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:31 下午 2021/11/22
|
||||
func (r *Random) GetServerNode(req *http.Request) (*define.ServerNode, error) {
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
if len(r.severList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
randomID := util.GetHashID(util.GenRandomString("", 128)) % uint64(len(r.severList))
|
||||
return r.severList[int(randomID)], nil
|
||||
}
|
114
balance/weight_serverRound_robin.go
Normal file
114
balance/weight_serverRound_robin.go
Normal file
@ -0,0 +1,114 @@
|
||||
// Package balance...
|
||||
//
|
||||
// Description : balance...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-22 6:58 下午
|
||||
package balance
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/gopkg/balance/define"
|
||||
)
|
||||
|
||||
// NewWeightServerRoundRobin ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:58 下午 2021/11/22
|
||||
func NewWeightServerRoundRobin(severList []*define.ServerNode) (IBalance, error) {
|
||||
if nil == severList || len(severList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
return &WeightServerRoundRobin{
|
||||
base: base{
|
||||
lock: &sync.RWMutex{},
|
||||
severList: severList,
|
||||
},
|
||||
effectiveWeight: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WeightServerRoundRobin 加权轮询
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 6:58 下午 2021/11/22
|
||||
type WeightServerRoundRobin struct {
|
||||
base
|
||||
effectiveWeight float64
|
||||
}
|
||||
|
||||
// GetServerNode ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 7:00 下午 2021/11/22
|
||||
func (w *WeightServerRoundRobin) GetServerNode(req *http.Request) (*define.ServerNode, error) {
|
||||
w.RLock()
|
||||
defer w.RUnlock()
|
||||
if len(w.severList) == 0 {
|
||||
return nil, errors.New("sever list is empty")
|
||||
}
|
||||
var expectBackendServer *define.ServerNode
|
||||
for _, backendServer := range w.severList {
|
||||
// 给每个后端服务增加自身权重
|
||||
backendServer.CurrentWeight += backendServer.Weight
|
||||
if expectBackendServer == nil {
|
||||
expectBackendServer = backendServer
|
||||
}
|
||||
if backendServer.CurrentWeight > expectBackendServer.CurrentWeight {
|
||||
expectBackendServer = backendServer
|
||||
}
|
||||
}
|
||||
// 把选择的后端服务权重减掉总权重
|
||||
expectBackendServer.CurrentWeight -= w.effectiveWeight
|
||||
return expectBackendServer, nil
|
||||
}
|
||||
|
||||
// AddServerNode 新添加一个服务器节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:07 下午 2021/10/20
|
||||
func (w *WeightServerRoundRobin) AddServerNode(node *define.ServerNode) error {
|
||||
if len(node.HostIP) == 0 || node.Port <= 0 {
|
||||
return errors.New("host ip or port is invalid")
|
||||
}
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
for _, item := range w.severList {
|
||||
if item.HostIP == node.HostIP && item.Port == node.Port {
|
||||
return errors.New("host config is already exist")
|
||||
}
|
||||
}
|
||||
w.effectiveWeight += node.Weight
|
||||
w.severList = append(w.severList, node)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove 移除一个节点, force = true , 强制删除, force = false 逻辑删除, 设置状态
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:19 下午 2021/10/20
|
||||
func (w *WeightServerRoundRobin) Remove(hostIP string, port int, force bool) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
tmpServerNode := make([]*define.ServerNode, 0)
|
||||
for _, item := range w.severList {
|
||||
if item.HostIP == hostIP && item.Port == port {
|
||||
if force {
|
||||
continue
|
||||
}
|
||||
item.Status = define.ServerNodeStatusRemove
|
||||
}
|
||||
tmpServerNode = append(tmpServerNode, item)
|
||||
}
|
||||
w.severList = tmpServerNode
|
||||
}
|
103
consistent_hash/consistent.go
Normal file
103
consistent_hash/consistent.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Package consistent_hash...
|
||||
//
|
||||
// Description : consistent_hash...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-21 4:57 下午
|
||||
package consistent_hash
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// New 获取实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:03 下午 2021/11/21
|
||||
func New(replicas int, fn HashFunc) *Consistent {
|
||||
if nil == fn {
|
||||
fn = DefaultHashFunc
|
||||
}
|
||||
return &Consistent{
|
||||
hashFunc: fn,
|
||||
replicas: replicas,
|
||||
keys: make([]int, 0),
|
||||
hashMap: make(map[int]string),
|
||||
lock: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// Consistent ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:00 下午 2021/11/21
|
||||
type Consistent struct {
|
||||
hashFunc HashFunc // 哈希函数
|
||||
replicas int // 虚拟的数量
|
||||
keys []int // 哈希环
|
||||
hashMap map[int]string // 虚拟节点与真实节点的映射表
|
||||
lock *sync.RWMutex // 锁
|
||||
}
|
||||
|
||||
// Add 添加节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:10 下午 2021/11/21
|
||||
func (c *Consistent) Add(keyList ...string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
for _, key := range keyList {
|
||||
for i := 0; i < c.replicas; i++ {
|
||||
hash := int(c.hashFunc([]byte(strconv.Itoa(i) + key)))
|
||||
c.keys = append(c.keys, hash)
|
||||
c.hashMap[hash] = key
|
||||
}
|
||||
}
|
||||
// 哈希值排序
|
||||
sort.Ints(c.keys)
|
||||
}
|
||||
|
||||
// Get 获取节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:16 下午 2021/11/21
|
||||
func (c *Consistent) Get(key string) string {
|
||||
c.lock.RLock()
|
||||
defer c.lock.Unlock()
|
||||
if len(c.keys) == 0 {
|
||||
return ""
|
||||
}
|
||||
hash := int(c.hashFunc([]byte(key)))
|
||||
// 查找节点索引
|
||||
idx := sort.Search(len(c.keys), func(i int) bool {
|
||||
return c.keys[i] >= hash
|
||||
})
|
||||
return c.hashMap[c.keys[idx%len(c.keys)]]
|
||||
}
|
||||
|
||||
// Delete 删除一个节点,本质逻辑 : 重建哈希环
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:35 下午 2021/11/21
|
||||
func (c *Consistent) Delete(key string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
tmpKeyList := make([]string, 0)
|
||||
for _, k := range c.hashMap {
|
||||
if k == key {
|
||||
continue
|
||||
}
|
||||
tmpKeyList = append(tmpKeyList, k)
|
||||
}
|
||||
c.hashMap = make(map[int]string)
|
||||
c.keys = make([]int, 0)
|
||||
c.Add(tmpKeyList...)
|
||||
}
|
22
consistent_hash/define.go
Normal file
22
consistent_hash/define.go
Normal file
@ -0,0 +1,22 @@
|
||||
// Package consistent_hash...
|
||||
//
|
||||
// Description : consistent_hash...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-21 4:49 下午
|
||||
package consistent_hash
|
||||
|
||||
import "hash/crc32"
|
||||
|
||||
// HashFunc 哈希函数定义
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:50 下午 2021/11/21
|
||||
type HashFunc func(data []byte) uint32
|
||||
|
||||
var (
|
||||
// DefaultHashFunc 默认的哈希函数
|
||||
DefaultHashFunc = crc32.ChecksumIEEE
|
||||
)
|
82
excel/create.go
Normal file
82
excel/create.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Package excel...
|
||||
//
|
||||
// Description : excel...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-19 12:25 下午
|
||||
package excel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
// NewExcel 获取excel实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:28 下午 2021/11/19
|
||||
func NewExcel() *Create {
|
||||
return &Create{
|
||||
fileHandler: excelize.NewFile(),
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建excel
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:27 下午 2021/11/19
|
||||
type Create struct {
|
||||
// fileHandler excel文件处理句柄
|
||||
fileHandler *excelize.File
|
||||
}
|
||||
|
||||
// GenerateSheet 生成sheet
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:43 下午 2021/11/19
|
||||
func (c *Create) GenerateSheet(sheetList []SheetData) error {
|
||||
for _, sheet := range sheetList {
|
||||
sheetIndex := c.fileHandler.NewSheet(sheet.Name)
|
||||
if sheet.IsDefault {
|
||||
// 设置活跃
|
||||
c.fileHandler.SetActiveSheet(sheetIndex)
|
||||
}
|
||||
for lineIdx, colList := range sheet.Data {
|
||||
for colIdx, col := range colList {
|
||||
position := c.getColPosition(colIdx, lineIdx)
|
||||
if err := c.fileHandler.SetCellValue(sheet.Name, position, col); nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save 保存文件
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:04 下午 2021/11/19
|
||||
func (c *Create) Save(fullFilePath string) error {
|
||||
return c.fileHandler.SaveAs(fullFilePath)
|
||||
}
|
||||
|
||||
// getColPosition 获取列名
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:14 下午 2021/11/19
|
||||
func (c *Create) getColPosition(colIndex int, dataLineIndex int) string {
|
||||
realIndex := colIndex % 26
|
||||
first := colIndex / 26
|
||||
if first == 0 {
|
||||
return fmt.Sprintf("%s%d", WordMap[realIndex], dataLineIndex+1)
|
||||
}
|
||||
return fmt.Sprintf("%s%s%d", WordMap[first], WordMap[realIndex], dataLineIndex+1)
|
||||
}
|
61
excel/define.go
Normal file
61
excel/define.go
Normal file
@ -0,0 +1,61 @@
|
||||
// Package excel...
|
||||
//
|
||||
// Description : excel...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-19 11:57 上午
|
||||
package excel
|
||||
|
||||
// ReadResult ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:57 上午 2021/11/19
|
||||
type ReadResult struct {
|
||||
Error error // 异常信息
|
||||
Result map[string][]map[string]interface{} // 查询结果 sheet => dataList
|
||||
}
|
||||
|
||||
// SheetData ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:35 下午 2021/11/19
|
||||
type SheetData struct {
|
||||
IsDefault bool // 是否默认工作表
|
||||
Name string // sheet 名称
|
||||
Data [][]interface{} // 数据列表
|
||||
}
|
||||
|
||||
var (
|
||||
// WordMap 单元格序号映射
|
||||
WordMap = map[int]string{
|
||||
0: "A",
|
||||
1: "B",
|
||||
2: "C",
|
||||
3: "D",
|
||||
4: "E",
|
||||
5: "F",
|
||||
6: "G",
|
||||
7: "H",
|
||||
8: "I",
|
||||
9: "J",
|
||||
10: "K",
|
||||
11: "L",
|
||||
12: "M",
|
||||
13: "N",
|
||||
14: "O",
|
||||
15: "P",
|
||||
16: "Q",
|
||||
17: "R",
|
||||
18: "S",
|
||||
19: "T",
|
||||
20: "U",
|
||||
21: "V",
|
||||
22: "W",
|
||||
23: "X",
|
||||
24: "Y",
|
||||
25: "Z",
|
||||
}
|
||||
)
|
174
excel/read.go
Normal file
174
excel/read.go
Normal file
@ -0,0 +1,174 @@
|
||||
// Package excel...
|
||||
//
|
||||
// Description : excel...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2021-11-19 3:59 下午
|
||||
package excel
|
||||
|
||||
import (
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
// NewRead 获取读取实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:00 下午 2021/11/19
|
||||
func NewRead(fullFilePath string, filePassword string) (*Read, error) {
|
||||
var err error
|
||||
read := &Read{}
|
||||
if read.fileHandler, err = excelize.OpenFile(fullFilePath, excelize.Options{Password: filePassword}); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return read, nil
|
||||
}
|
||||
|
||||
// Read ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:03 下午 2021/11/19
|
||||
type Read struct {
|
||||
fileHandler *excelize.File
|
||||
}
|
||||
|
||||
// GetAllSheetList ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:06 下午 2021/11/19
|
||||
func (r *Read) GetAllSheetList() []string {
|
||||
return r.fileHandler.GetSheetList()
|
||||
}
|
||||
|
||||
// GetAllData 读取全部数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:07 下午 2021/11/19
|
||||
func (r *Read) GetAllData() (map[string][][]string, error) {
|
||||
var (
|
||||
sheetList []string
|
||||
result map[string][][]string
|
||||
err error
|
||||
)
|
||||
sheetList = r.GetAllSheetList()
|
||||
result = make(map[string][][]string)
|
||||
for _, sheetName := range sheetList {
|
||||
if result[sheetName], err = r.fileHandler.GetRows(sheetName); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetAllDataToMap 读取全部数据,并返回map结构
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:20 下午 2021/11/19
|
||||
func (r *Read) GetAllDataToMap(fieldList []string) (map[string][]map[string]string, error) {
|
||||
var (
|
||||
allData map[string][][]string
|
||||
err error
|
||||
formatResult map[string][]map[string]string
|
||||
)
|
||||
formatResult = make(map[string][]map[string]string)
|
||||
if allData, err = r.GetAllData(); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
for sheetName, sheetData := range allData {
|
||||
formatResult[sheetName] = make([]map[string]string, 0)
|
||||
for _, lineData := range sheetData {
|
||||
tmpResult := make(map[string]string)
|
||||
for idx, colData := range lineData {
|
||||
if idx >= len(fieldList) {
|
||||
// 指定的字段列表较短, 自动剔除后面的字段
|
||||
break
|
||||
}
|
||||
tmpResult[fieldList[idx]] = colData
|
||||
}
|
||||
// 字段列表较长, 单元格不足, 自动补齐空字符串
|
||||
for i := len(lineData); i < len(fieldList); i++ {
|
||||
tmpResult[fieldList[i]] = ""
|
||||
}
|
||||
formatResult[sheetName] = append(formatResult[sheetName], tmpResult)
|
||||
}
|
||||
}
|
||||
// 格式化数据
|
||||
return formatResult, nil
|
||||
}
|
||||
|
||||
// ExtractAssignCol 抽取指定的列,并返回list数据, 列的计数从 0 开始
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:53 下午 2021/11/19
|
||||
func (r *Read) ExtractAssignCol(colIndexList []int) (map[string][][]string, error) {
|
||||
var (
|
||||
allData map[string][][]string
|
||||
err error
|
||||
formatResult map[string][][]string
|
||||
)
|
||||
if allData, err = r.GetAllData(); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
formatResult = make(map[string][][]string)
|
||||
for sheetName, sheetData := range allData {
|
||||
formatResult[sheetName] = make([][]string, 0)
|
||||
for _, lineData := range sheetData {
|
||||
tmpData := make([]string, 0)
|
||||
for _, colIdx := range colIndexList {
|
||||
if len(lineData) <= colIdx {
|
||||
// 索引越界,默认空值
|
||||
tmpData = append(tmpData, "")
|
||||
continue
|
||||
}
|
||||
tmpData = append(tmpData, lineData[colIdx])
|
||||
}
|
||||
formatResult[sheetName] = append(formatResult[sheetName], tmpData)
|
||||
}
|
||||
}
|
||||
return formatResult, nil
|
||||
}
|
||||
|
||||
// ExtractAssignColToMap 抽取指定的列,并返回map数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 4:53 下午 2021/11/19
|
||||
func (r *Read) ExtractAssignColToMap(ruleTable map[int]string) (map[string][]map[string]string, error) {
|
||||
var (
|
||||
allData map[string][][]string
|
||||
err error
|
||||
formatResult map[string][]map[string]string
|
||||
)
|
||||
formatResult = make(map[string][]map[string]string)
|
||||
if allData, err = r.GetAllData(); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
for sheetName, sheetData := range allData {
|
||||
formatResult[sheetName] = make([]map[string]string, 0)
|
||||
for _, lineData := range sheetData {
|
||||
tmpResult := make(map[string]string)
|
||||
for idx, colData := range lineData {
|
||||
colName, exist := ruleTable[idx]
|
||||
if !exist {
|
||||
// 当前字段不需要提取
|
||||
continue
|
||||
}
|
||||
tmpResult[colName] = colData
|
||||
}
|
||||
for _, colName := range ruleTable {
|
||||
if _, exist := tmpResult[colName]; !exist {
|
||||
tmpResult[colName] = ""
|
||||
}
|
||||
}
|
||||
formatResult[sheetName] = append(formatResult[sheetName], tmpResult)
|
||||
}
|
||||
}
|
||||
// 格式化数据
|
||||
return formatResult, nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Package gin ...
|
||||
// Package api ...
|
||||
//
|
||||
// Description : 便捷的相关API处理
|
||||
//
|
||||
@ -23,7 +23,7 @@ type IApi interface {
|
||||
GetURI() string
|
||||
// GetMiddleWareList 使用的中间件列表
|
||||
GetMiddleWareList() []gin.HandlerFunc
|
||||
// 处理的handler
|
||||
// GetHandler 处理的handler
|
||||
GetHandler() gin.HandlerFunc
|
||||
}
|
||||
|
||||
|
10
go.mod
10
go.mod
@ -14,6 +14,7 @@ require (
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/gjson v1.9.0
|
||||
github.com/xuri/excelize/v2 v2.4.1
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
||||
go.uber.org/zap v1.19.1
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
@ -54,19 +55,24 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/pierrec/lz4 v2.6.0+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.3 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.1 // indirect
|
||||
github.com/tidwall/match v1.0.3 // indirect
|
||||
github.com/tidwall/pretty v1.1.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
|
24
go.sum
24
go.sum
@ -121,6 +121,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@ -143,6 +145,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI=
|
||||
github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible h1:LTLpUnfX81MkHeCtSrwNKZwuW5Id6kCa7/P43NdcNn4=
|
||||
github.com/shirou/gopsutil v3.21.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
@ -170,6 +176,10 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/xdg/scram v1.0.3/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o=
|
||||
github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.4.1 h1:veeeFLAJwsNEBPBlDepzPIYS1eLyBVcXNZUW79exZ1E=
|
||||
github.com/xuri/excelize/v2 v2.4.1/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A=
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ=
|
||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -187,8 +197,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@ -203,8 +217,11 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -233,8 +250,9 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
26
util/ip.go
26
util/ip.go
@ -7,7 +7,10 @@
|
||||
// Date : 2021-03-09 5:56 下午
|
||||
package util
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetHostIP 获取本机IP地址
|
||||
//
|
||||
@ -27,3 +30,24 @@ func GetHostIP() string {
|
||||
}
|
||||
return hostIP
|
||||
}
|
||||
|
||||
// GetRemoteIp 获取远端IP
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:35 下午 2021/11/22
|
||||
func GetRemoteIp(req *http.Request) string {
|
||||
|
||||
// Try via request
|
||||
|
||||
ip, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||
|
||||
if err != nil {
|
||||
return "::1"
|
||||
}
|
||||
userIP := net.ParseIP(ip)
|
||||
if userIP == nil {
|
||||
return "::1"
|
||||
}
|
||||
return userIP.String()
|
||||
}
|
||||
|
Reference in New Issue
Block a user