上传lego 框架代码

This commit is contained in:
liwei1dao 2022-06-07 20:18:22 +08:00
parent aa47570de9
commit 6a7f120755
189 changed files with 18115 additions and 285 deletions

View File

@ -4,7 +4,7 @@ import (
"go_dreamfactory/comm" "go_dreamfactory/comm"
"go_dreamfactory/pb" "go_dreamfactory/pb"
"github.com/liwei1dao/lego/sys/log" "go_dreamfactory/lego/sys/log"
) )
func (r *Robot) handleUserMsg(msg *pb.UserMessage) { func (r *Robot) handleUserMsg(msg *pb.UserMessage) {

View File

@ -4,8 +4,9 @@ import (
"go_dreamfactory/pb" "go_dreamfactory/pb"
"reflect" "reflect"
"github.com/liwei1dao/lego/core" "go_dreamfactory/lego/core"
"github.com/liwei1dao/lego/sys/log" "go_dreamfactory/lego/sys/log"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )

View File

@ -5,8 +5,9 @@ import (
"fmt" "fmt"
"go_dreamfactory/pb" "go_dreamfactory/pb"
"github.com/liwei1dao/lego/base" "go_dreamfactory/lego/base"
"github.com/liwei1dao/lego/sys/log" "go_dreamfactory/lego/sys/log"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )

35
go.mod
View File

@ -3,15 +3,30 @@ module go_dreamfactory
go 1.18 go 1.18
require ( require (
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/go-playground/validator/v10 v10.10.1
github.com/go-redis/redis/v8 v8.11.5
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/consul/api v1.12.0
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/liwei1dao/lego v0.0.0-20220531091126-a21bb3766fbc github.com/mitchellh/hashstructure v1.1.0
github.com/nacos-group/nacos-sdk-go v1.0.8
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/robfig/cron/v3 v3.0.1
github.com/rs/xid v1.3.0
github.com/satori/go.uuid v1.2.0
github.com/smallnest/rpcx v1.7.4
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.1 github.com/stretchr/testify v1.7.1
github.com/ugorji/go/codec v1.2.7
go.mongodb.org/mongo-driver v1.5.1 go.mongodb.org/mongo-driver v1.5.1
go.uber.org/zap v1.21.0
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3
google.golang.org/protobuf v1.28.0 google.golang.org/protobuf v1.28.0
gopkg.in/yaml.v2 v2.4.0
) )
require ( require (
@ -20,7 +35,6 @@ require (
github.com/apache/thrift v0.16.0 // indirect github.com/apache/thrift v0.16.0 // indirect
github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-metrics v0.3.10 // indirect
github.com/aws/aws-sdk-go v1.34.28 // indirect github.com/aws/aws-sdk-go v1.34.28 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect
github.com/cenk/backoff v2.2.1+incompatible // indirect github.com/cenk/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect
@ -39,15 +53,12 @@ require (
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect
github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.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-redis/redis/v8 v8.11.5 // indirect
github.com/go-stack/stack v1.8.0 // indirect github.com/go-stack/stack v1.8.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/hashicorp/consul/api v1.12.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.2.0 // indirect github.com/hashicorp/go-hclog v1.2.0 // indirect
@ -75,33 +86,25 @@ require (
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/miekg/dns v1.1.48 // indirect github.com/miekg/dns v1.1.48 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/hashstructure v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nacos-group/nacos-sdk-go v1.0.8 // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/nxadm/tail v1.4.8 // indirect github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect
github.com/philhofer/fwd v1.1.1 // indirect github.com/philhofer/fwd v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rpcxio/libkv v0.5.1-0.20210420120011-1fceaedca8a5 // indirect github.com/rpcxio/libkv v0.5.1-0.20210420120011-1fceaedca8a5 // indirect
github.com/rs/cors v1.8.2 // indirect github.com/rs/cors v1.8.2 // indirect
github.com/rs/xid v1.3.0 // indirect
github.com/rubyist/circuitbreaker v2.2.1+incompatible // indirect github.com/rubyist/circuitbreaker v2.2.1+incompatible // indirect
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 // indirect github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 // indirect github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 // indirect
github.com/smallnest/rpcx v1.7.4 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tinylib/msgp v1.1.6 // indirect github.com/tinylib/msgp v1.1.6 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fastrand v1.1.0 // indirect github.com/valyala/fastrand v1.1.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
@ -115,19 +118,15 @@ require (
go.opentelemetry.io/otel/trace v1.6.3 // indirect go.opentelemetry.io/otel/trace v1.6.3 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.10 // indirect golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )
// replace github.com/liwei1dao/lego => F:\work\go\lego

195
go.sum
View File

@ -17,7 +17,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 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.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.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= 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.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
@ -30,7 +29,6 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 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/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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/firestore v1.5.0/go.mod h1:c4nNYR1qdq7eaZ+jSc5fonrQN2k3M7sWATcYTiakjEo=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 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.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.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -45,47 +43,25 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
firebase.google.com/go/v4 v4.7.1/go.mod h1:UgGSTOhEZVbB2L3dQ3z4pThDTiH869i8TDAZKnrHKbU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU=
github.com/AthenZ/athenz v1.10.39/go.mod h1:3Tg8HLsiQZp81BJY58JBeU2BR6B/H4/0MQGfCwhHNEA=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw= github.com/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/Shopify/sarama v1.30.1/go.mod h1:hGgx05L/DiW8XYBXeJdKIN6V2QUy2H6JqME5VT1NLRw=
github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/ZZMarquis/gm v1.3.2/go.mod h1:wWbjZYgruQVd7Bb8UkSN8ujU931kx2XUW6nZLCiDE0Q=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 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/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-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-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 h1:H7Mq9zsKIMvBaw7rEmbWULvSTF2UI/9lFvvm4d/NZdk= github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 h1:H7Mq9zsKIMvBaw7rEmbWULvSTF2UI/9lFvvm4d/NZdk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.885/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/aliyun/alibaba-cloud-sdk-go v1.61.885/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
github.com/antchfx/xmlquery v1.2.4/go.mod h1:KQQuESaxSlqugE2ZBcM/qn+ebIpt+d+4Xx7YcSGAIrM=
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xpath v1.1.8/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/pulsar-client-go v0.8.0/go.mod h1:kpFNN3AqZWQEGcRnhu0rNhWLI91+6RDYqPbmNEiIsWs=
github.com/apache/pulsar-client-go/oauth2 v0.0.0-20220120090717-25e59572242e/go.mod h1:Xee4tgYLFpYcPMcTfBYWE1uKRzeciodGTSEDMzsR6i8=
github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY=
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/ardielle/ardielle-go v1.5.2/go.mod h1:I4hy1n795cUhaVt/ojz83SNVCYIGsAFAONtv2Dr7HUI=
github.com/ardielle/ardielle-tools v1.5.4/go.mod h1:oZN+JRMnqGiIhrzkRN9l26Cej9dEx4jeNG6A+AdkShk=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 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-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
@ -93,13 +69,10 @@ github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.32.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk= github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beefsack/go-rate v0.0.0-20180408011153-efa7637bb9b6/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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 v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -107,7 +80,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
@ -133,30 +105,17 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-jump v0.0.0-20170409065014-e1f439676b57/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA= github.com/dgryski/go-jump v0.0.0-20170409065014-e1f439676b57/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA=
github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 h1:0wH6nO9QEa02Qx8sIQGw6ieKdz+BXjpccSOo9vXNl4U= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 h1:0wH6nO9QEa02Qx8sIQGw6ieKdz+BXjpccSOo9vXNl4U=
github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.3.1/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
github.com/edwingeng/doublejump v0.0.0-20210724020454-c82f1bcb3280 h1:t04U/MQCFMNbKQ1YdqsZe8MQIgYB4gGOX87CQIrStqw= github.com/edwingeng/doublejump v0.0.0-20210724020454-c82f1bcb3280 h1:t04U/MQCFMNbKQ1YdqsZe8MQIgYB4gGOX87CQIrStqw=
github.com/edwingeng/doublejump v0.0.0-20210724020454-c82f1bcb3280/go.mod h1:+RhzcuwqMSuWjEJrOKR19t+Wc8Ca7OuUYQ//CReOIwI= github.com/edwingeng/doublejump v0.0.0-20210724020454-c82f1bcb3280/go.mod h1:+RhzcuwqMSuWjEJrOKR19t+Wc8Ca7OuUYQ//CReOIwI=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -176,18 +135,13 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
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.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 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 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@ -195,18 +149,13 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/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.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.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.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.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4=
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
@ -227,7 +176,6 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
@ -252,20 +200,13 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA=
github.com/gocolly/colly/v2 v2.1.0/go.mod h1:I2MuhsLjQ+Ex+IzK3afNS8/1qP3AedHOusRPcRdC5o0=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godror/godror v0.25.3/go.mod h1:JgtdZ1iSaNoioa/B53BVVWji9J9iGPDDj2763T5d1So=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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-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-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -302,7 +243,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -335,7 +275,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/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-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-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/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/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@ -348,13 +287,8 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 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/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE= github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
@ -362,7 +296,6 @@ github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfc
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.8.1/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= github.com/hashicorp/consul/api v1.8.1/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk=
github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY=
@ -386,9 +319,8 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
@ -397,14 +329,12 @@ github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 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.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/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-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/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 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.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/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -429,38 +359,21 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb-client-go/v2 v2.8.2/go.mod h1:x7Jo5UHHl+w8wu8UnGiNobDDHygojXwJX4mx7rXGKMk=
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/jawher/mow.cli v1.0.4/go.mod h1:5hQj2V8g+qYmLUVWqu4Wuja1pI57M83EChYLVZ0sMKk=
github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg=
github.com/jawher/mow.cli v1.2.0/go.mod h1:y+pcA3jBAdo/GIZx/0rFjw/K2bVEODP9rfZOfaiq8Ko=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jlaffaye/ftp v0.0.0-20220309012535-813c8a838452/go.mod h1:oZaomI+9/et52UBjvNU9LCIqmgt816+7ljXCx0EIPzo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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.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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
@ -473,17 +386,13 @@ github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSg
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kavu/go_reuseport v1.5.0 h1:UNuiY2OblcqAtVDE8Gsg1kZz8zbBWg907sP1ceBV+bk= github.com/kavu/go_reuseport v1.5.0 h1:UNuiY2OblcqAtVDE8Gsg1kZz8zbBWg907sP1ceBV+bk=
github.com/kavu/go_reuseport v1.5.0/go.mod h1:CG8Ee7ceMFSMnx/xr25Vm0qXaj2Z4i5PWoUx+JZ5/CU= github.com/kavu/go_reuseport v1.5.0/go.mod h1:CG8Ee7ceMFSMnx/xr25Vm0qXaj2Z4i5PWoUx+JZ5/CU=
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@ -493,7 +402,6 @@ github.com/klauspost/reedsolomon v1.9.16 h1:mR0AwphBwqFv/I3B9AHtNKvzuowI1vrj8/3U
github.com/klauspost/reedsolomon v1.9.16/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= github.com/klauspost/reedsolomon v1.9.16/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
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.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
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/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/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -506,8 +414,6 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 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/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo= github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo=
@ -516,20 +422,12 @@ github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgU
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8= github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8=
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5jFF4BHGAEDSqwPW1NJS3XshxbRCxtjFAZc= github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5jFF4BHGAEDSqwPW1NJS3XshxbRCxtjFAZc=
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0= github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/linkedin/goavro/v2 v2.9.8/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/liwei1dao/dm v0.0.0-20211103094420-938edf103cf0/go.mod h1:YH8wwRWv57a88ZbPtflEhwCQDrcm9L9S8wl9y1m8SnQ=
github.com/liwei1dao/lego v0.0.0-20220531091126-a21bb3766fbc h1:rbrKM+1M18uV1v+fvI/CeQhygPO57UtFo2UiU+NWQJs=
github.com/liwei1dao/lego v0.0.0-20220531091126-a21bb3766fbc/go.mod h1:eEEe2/9fK64Bo1Mj30Hwdt5BZ8IwKbZ6ZMgCTu8DQ+4=
github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0=
github.com/lucas-clemente/quic-go v0.27.0 h1:v6WY87q9zD4dKASbG8hy/LpzAVNzEQzw8sEIeloJsc4= github.com/lucas-clemente/quic-go v0.27.0 h1:v6WY87q9zD4dKASbG8hy/LpzAVNzEQzw8sEIeloJsc4=
github.com/lucas-clemente/quic-go v0.27.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lucas-clemente/quic-go v0.27.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
@ -542,25 +440,20 @@ github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWCh
github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y= github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y=
github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@ -574,10 +467,8 @@ github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXx
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
@ -595,20 +486,11 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 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/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 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/nacos-group/nacos-sdk-go v1.0.8 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM= github.com/nacos-group/nacos-sdk-go v1.0.8 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM=
github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA= github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M=
github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU=
github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -631,7 +513,6 @@ github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
@ -642,8 +523,6 @@ github.com/peterbourgon/g2s v0.0.0-20140925154142-ec76db4c1ac1 h1:5Dl+ADmsGerAqH
github.com/peterbourgon/g2s v0.0.0-20140925154142-ec76db4c1ac1/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg= github.com/peterbourgon/g2s v0.0.0-20140925154142-ec76db4c1ac1/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
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/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -658,8 +537,6 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 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.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
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-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-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.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -667,14 +544,10 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 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.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
@ -696,8 +569,6 @@ github.com/rubyist/circuitbreaker v2.2.1+incompatible/go.mod h1:Ycs3JgJADPuzJDwf
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 h1:AJNDS0kP60X8wwWFvbLPwDuojxubj9pbfK7pjHw0vKg= github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 h1:AJNDS0kP60X8wwWFvbLPwDuojxubj9pbfK7pjHw0vKg=
github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
@ -706,7 +577,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
@ -734,15 +604,12 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 h1:J8xk0QMMrqfDLqU0m07pYRRiOIlE7I3dNWAp/pAHqfo= github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 h1:J8xk0QMMrqfDLqU0m07pYRRiOIlE7I3dNWAp/pAHqfo=
github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6/go.mod h1:h+J5yoLzf3XMKtM9l4vOaUtS4e+si6T3sKDtheJ15wc= github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6/go.mod h1:h+J5yoLzf3XMKtM9l4vOaUtS4e+si6T3sKDtheJ15wc=
github.com/smallnest/rpcx v1.7.4 h1:u6ADk/Ep8BqtAoJZO7LbniWsP+nqeAtcbaPm2D4eOXg= github.com/smallnest/rpcx v1.7.4 h1:u6ADk/Ep8BqtAoJZO7LbniWsP+nqeAtcbaPm2D4eOXg=
github.com/smallnest/rpcx v1.7.4/go.mod h1:TSciUoPlm8MYxnC7ErCz5ZymOFxOTbhN9cRgEI6Degs= github.com/smallnest/rpcx v1.7.4/go.mod h1:TSciUoPlm8MYxnC7ErCz5ZymOFxOTbhN9cRgEI6Degs=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0=
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@ -750,7 +617,6 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 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.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@ -763,7 +629,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= 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.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -778,7 +643,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto= github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto=
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
@ -795,20 +659,16 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= 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/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/wolfogre/go-pprof-practice v0.0.0-20190402114113-8ce266a210ee/go.mod h1:bwtOR7TyudY1IW9h5rVzpkyOkcwPPxinKAxIrdMnN+Q=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
@ -868,31 +728,21 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM= golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-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-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-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
@ -902,10 +752,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/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-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/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 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-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -933,7 +781,6 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -962,14 +809,11 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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-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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/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-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-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-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-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-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/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-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-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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@ -979,7 +823,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/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-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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/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-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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
@ -987,7 +830,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 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-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -1041,9 +883,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1054,7 +894,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-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-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-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-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-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1070,10 +909,7 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1081,9 +917,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/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-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-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-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210223095934-7937bea0104d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/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-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1093,7 +927,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-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-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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1102,7 +935,6 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/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-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw=
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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/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.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1119,14 +951,10 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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-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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/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-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-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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@ -1135,7 +963,6 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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-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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@ -1185,7 +1012,6 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/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-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@ -1199,10 +1025,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
@ -1276,7 +1098,6 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/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-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-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/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-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-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-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@ -1334,7 +1155,6 @@ gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 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/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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -1359,7 +1179,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
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.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/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/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=

85
lego/base/core.go Normal file
View File

@ -0,0 +1,85 @@
package base
import (
"context"
"go_dreamfactory/lego/core"
"github.com/smallnest/rpcx/client"
)
type Result struct {
Index string
Result interface{}
Err error
}
type ISingleService interface {
core.IService
}
type IClusterServiceBase interface {
core.IService
GetTag() string //获取集群标签
GetCategory() core.S_Category //服务类别 例如游戏服
GetRpcId() string //获取rpc通信id
GetPreWeight() float64 //集群服务负载值 暂时可以不用理会
SetPreWeight(weight int32) //设置服务器权重
}
type IClusterServiceSession interface {
GetId() string
GetIp() string
GetRpcId() string
GetType() string
GetVersion() string
SetVersion(v string)
GetPreWeight() float64
SetPreWeight(p float64)
Done()
CallNR(_func core.Rpc_Key, params ...interface{}) (err error)
Call(_func core.Rpc_Key, params ...interface{}) (interface{}, error)
}
type IClusterService interface {
IClusterServiceBase
GetSessionsByCategory(category core.S_Category) (ss []IClusterServiceSession) //按服务类别获取服务列表
DefauleRpcRouteRules(stype string, sip string) (ss IClusterServiceSession, err error) //默认rpc路由规则
RpcInvokeById(sId string, rkey core.Rpc_Key, iscall bool, arg ...interface{}) (result interface{}, err error)
RpcInvokeByIds(sId []string, rkey core.Rpc_Key, iscall bool, arg ...interface{}) (results map[string]*Result, err error) //执行远程服务Rpc方法
RpcInvokeByType(sType string, rkey core.Rpc_Key, iscall bool, arg ...interface{}) (result interface{}, err error) //根据路由规则执行远程方法
RpcInvokeByIp(sIp, sType string, rkey core.Rpc_Key, iscall bool, arg ...interface{}) (result interface{}, err error) //根据目标IP和类型执行远程方法
RpcInvokeByIps(sIp []string, sType string, rkey core.Rpc_Key, iscall bool, arg ...interface{}) (results map[string]*Result, err error) //根据目标IP集和类型执行远程方法
ReleaseRpc(rkey core.Rpc_Key, arg ...interface{}) //发布Rpc
Register(id core.Rpc_Key, f interface{}) //注册RPC远程方法
RegisterGO(id core.Rpc_Key, f interface{}) //注册RPC远程方法
//废弃此方法
Subscribe(id core.Rpc_Key, f interface{}) (err error) //订阅Rpc
UnSubscribe(id core.Rpc_Key, f interface{}) (err error) //订阅Rpc
}
type IRPCXServiceSession interface {
GetId() string
GetIp() string
GetRpcId() string
GetType() string
GetVersion() string
SetVersion(v string)
GetPreWeight() float64
SetPreWeight(p float64)
Done()
Call(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) error
Go(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) (*client.Call, error)
}
type IRPCXService interface {
IClusterServiceBase
DefauleRpcRouteRules(stype string, sip string) (ss IRPCXServiceSession, err error) //默认rpc路由规则
Register(rcvr interface{}) (err error)
RegisterFunction(fn interface{}) (err error)
RegisterFunctionName(name string, fn interface{}) (err error)
RpcCallById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error)
RpcGoById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error)
RpcCallByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error)
RpcGoByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error)
}

66
lego/base/rpcx/options.go Normal file
View File

@ -0,0 +1,66 @@
package rpcx
import (
"fmt"
"io/ioutil"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/utils/container/ip"
"gopkg.in/yaml.v2"
)
type Option func(*Options)
type Options struct {
ConfPath string
Version string //服务版本
Setting core.ServiceSttings
}
func SetConfPath(v string) Option {
return func(o *Options) {
o.ConfPath = v
}
}
func SetVersion(v string) Option {
return func(o *Options) {
o.Version = v
}
}
// func SetSetting(v core.ServiceSttings) Option {
// return func(o *Options) {
// o.Setting = v
// }
// }
func newOptions(option ...Option) *Options {
options := &Options{
ConfPath: "conf/cluster.yaml",
}
for _, o := range option {
o(options)
}
// confpath := fmt.Sprintf("conf/%s.toml", options.Id)
yamlFile, err := ioutil.ReadFile(options.ConfPath)
if err != nil {
panic(fmt.Sprintf("读取服务配置【%s】文件失败err:%v:", options.ConfPath, err))
}
err = yaml.Unmarshal(yamlFile, &options.Setting)
if err != nil {
panic(fmt.Sprintf("读取服务配置【%s】文件失败err:%v:", options.ConfPath, err))
}
if len(options.Setting.Id) == 0 || len(options.Setting.Type) == 0 || len(options.Setting.Tag) == 0 {
panic(fmt.Sprintf("[%s] 配置缺少必要配置: %+v", options.ConfPath, options))
}
if len(options.Setting.Ip) == 0 {
if ipinfo := ip.GetEthernetInfo(); ipinfo != nil { //获取以太网Ip地址
options.Setting.Ip = ipinfo.IP
} else {
options.Setting.Ip = ip.GetOutboundIP() //局域网ip
}
}
return options
}

358
lego/base/rpcx/service.go Normal file
View File

@ -0,0 +1,358 @@
package rpcx
import (
"context"
"fmt"
"runtime"
"sync"
"go_dreamfactory/lego"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/cron"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/registry"
"go_dreamfactory/lego/sys/rpcx"
"go_dreamfactory/lego/utils/container/sortslice"
"go_dreamfactory/lego/utils/container/version"
"github.com/smallnest/rpcx/client"
)
type RPCXService struct {
cbase.ServiceBase
opts *Options
serverList sync.Map
rpcxService base.IRPCXService
IsInClustered bool
lock sync.RWMutex //服务锁
}
func (this *RPCXService) GetTag() string {
return this.opts.Setting.Tag
}
func (this *RPCXService) GetId() string {
return this.opts.Setting.Id
}
func (this *RPCXService) GetType() string {
return this.opts.Setting.Type
}
func (this *RPCXService) GetIp() string {
return this.opts.Setting.Ip
}
func (this *RPCXService) GetPort() int {
return this.opts.Setting.Port
}
func (this *RPCXService) GetCategory() core.S_Category {
return this.opts.Setting.Category
}
func (this *RPCXService) GetVersion() string {
return this.opts.Version
}
func (this *RPCXService) GetSettings() core.ServiceSttings {
return this.opts.Setting
}
func (this *RPCXService) GetRpcId() string {
return ""
}
func (this *RPCXService) GetPreWeight() float64 {
return float64(1) / float64(runtime.NumGoroutine())
}
func (this *RPCXService) SetPreWeight(weight int32) {
}
func (this *RPCXService) Options() *Options {
return this.opts
}
func (this *RPCXService) Configure(opts ...Option) {
this.opts = newOptions(opts...)
}
func (this *RPCXService) Init(service core.IService) (err error) {
this.rpcxService = service.(base.IRPCXService)
return this.ServiceBase.Init(service)
}
func (this *RPCXService) InitSys() {
if err := log.OnInit(this.opts.Setting.Sys["log"]); err != nil {
panic(fmt.Sprintf("Sys log Init err:%v", err))
} else {
log.Infof("Sys log Init success !")
}
if err := event.OnInit(this.opts.Setting.Sys["event"]); err != nil {
log.Panicf(fmt.Sprintf("Sys event Init err:%v", err))
} else {
log.Infof("Sys event Init success !")
}
if err := registry.OnInit(this.opts.Setting.Sys["registry"], registry.SetService(this.rpcxService), registry.SetListener(this.rpcxService.(registry.IListener))); err != nil {
log.Panicf(fmt.Sprintf("Sys registry Init err:%v", err))
} else {
log.Infof("Sys registry Init success !")
}
if err := rpcx.OnInit(this.opts.Setting.Sys["rpcx"], rpcx.SetServiceId(this.GetId()), rpcx.SetPort(this.GetPort())); err != nil {
log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err))
} else {
log.Infof("Sys rpcx Init success !")
}
event.Register(core.Event_ServiceStartEnd, func() { //阻塞 先注册服务集群 保证其他服务能及时发现
if err := rpcx.Start(); err != nil {
log.Panicf(fmt.Sprintf("Sys rpcx Start err:%v", err))
}
if err := registry.Start(); err != nil {
log.Panicf(fmt.Sprintf("Sys registry Start err:%v", err))
}
})
}
func (this *RPCXService) Start() (err error) {
if err = this.ServiceBase.Start(); err != nil {
return
}
return
}
func (this *RPCXService) Run(mod ...core.IModule) {
modules := make([]core.IModule, 0)
modules = append(modules, mod...)
this.ServiceBase.Run(modules...)
}
func (this *RPCXService) Destroy() (err error) {
if err = rpcx.Stop(); err != nil {
return
}
if err = registry.Stop(); err != nil {
return
}
cron.Stop()
err = this.ServiceBase.Destroy()
return
}
//注册服务会话 当有新的服务加入时
func (this *RPCXService) FindServiceHandlefunc(node registry.ServiceNode) {
this.lock.Lock()
if _, ok := this.serverList.Load(node.Id); !ok {
if s, err := NewServiceSession(&node); err != nil {
log.Errorf("创建服务会话失败【%s】 err:%v", node.Id, err)
} else {
this.serverList.Store(node.Id, s)
}
}
this.lock.Unlock()
if this.IsInClustered {
event.TriggerEvent(core.Event_FindNewService, node) //触发发现新的服务事件
} else {
if node.Id == this.opts.Setting.Id { //发现自己 加入集群成功
this.IsInClustered = true
event.TriggerEvent(core.Event_RegistryStart)
}
}
}
//更新服务会话 当有新的服务加入时
func (this *RPCXService) UpDataServiceHandlefunc(node registry.ServiceNode) {
if ss, ok := this.serverList.Load(node.Id); ok { //已经在缓存中 需要更新节点信息
session := ss.(base.IRPCXServiceSession)
if session.GetRpcId() != node.RpcId {
if s, err := NewServiceSession(&node); err != nil {
log.Errorf("更新服务会话失败【%s】 err:%v", node.Id, err)
} else {
this.serverList.Store(node.Id, s)
}
event.TriggerEvent(core.Event_FindNewService, node) //触发发现新的服务事件
} else {
if session.GetVersion() != node.Version {
session.SetVersion(node.Version)
}
if session.GetPreWeight() != node.PreWeight {
session.SetPreWeight(node.PreWeight)
}
event.TriggerEvent(core.Event_UpDataOldService, node) //触发发现新的服务事件
}
}
}
//注销服务会话
func (this *RPCXService) LoseServiceHandlefunc(sId string) {
this.lock.Lock()
session, ok := this.serverList.Load(sId)
if ok && session != nil {
session.(base.IRPCXServiceSession).Done()
this.serverList.Delete(sId)
}
this.lock.Unlock()
event.TriggerEvent(core.Event_LoseService, sId) //触发发现新的服务事件
}
func (this *RPCXService) getServiceSessionByType(sType string, sIp string) (ss []base.IRPCXServiceSession, err error) {
ss = make([]base.IRPCXServiceSession, 0)
if nodes := registry.GetServiceByType(sType); nodes == nil {
log.Errorf("获取目标类型 type【%s】ip [%s] 服务集失败", sType, sIp)
return nil, err
} else {
if sIp == core.AutoIp {
for _, v := range nodes {
if s, ok := this.serverList.Load(v.Id); ok {
ss = append(ss, s.(base.IRPCXServiceSession))
} else {
s, err = NewServiceSession(v)
if err != nil {
log.Errorf("创建服务会话失败【%s】 err:%v", v.Id, err)
continue
} else {
this.serverList.Store(v.Id, s)
ss = append(ss, s.(base.IRPCXServiceSession))
}
}
}
} else {
for _, v := range nodes {
if v.IP == sIp {
if s, ok := this.serverList.Load(v.Id); ok {
ss = append(ss, s.(base.IRPCXServiceSession))
} else {
s, err = NewServiceSession(v)
if err != nil {
log.Errorf("创建服务会话失败【%s】 err:%v", v.Id, err)
continue
} else {
this.serverList.Store(v.Id, s)
ss = append(ss, s.(base.IRPCXServiceSession))
}
}
}
}
}
}
return
}
//默认路由规则
func (this *RPCXService) DefauleRpcRouteRules(stype string, sip string) (ss base.IRPCXServiceSession, err error) {
if s, e := this.getServiceSessionByType(stype, sip); e != nil {
return nil, e
} else {
ss := make([]interface{}, len(s))
for i, v := range s {
ss[i] = v
}
if len(ss) > 0 {
//排序找到最优服务
sortslice.Sort(ss, func(a interface{}, b interface{}) int8 {
as := a.(base.IRPCXServiceSession)
bs := b.(base.IRPCXServiceSession)
if iscompare := version.CompareStrVer(as.GetVersion(), bs.GetVersion()); iscompare != 0 {
return iscompare
} else {
if as.GetPreWeight() < bs.GetPreWeight() {
return 1
} else if as.GetPreWeight() > bs.GetPreWeight() {
return -1
} else {
return 0
}
}
})
return ss[0].(base.IRPCXServiceSession), nil
} else {
return nil, fmt.Errorf("未找到IP[%s]类型%s】的服务信息", sip, stype)
}
}
}
//注册服务对象
func (this *RPCXService) Register(rcvr interface{}) (err error) {
err = rpcx.Register(rcvr)
return
}
//注册服务方法
func (this *RPCXService) RegisterFunction(fn interface{}) (err error) {
err = rpcx.RegisterFunction(fn)
return
}
//注册服务方法 自定义方法名称
func (this *RPCXService) RegisterFunctionName(name string, fn interface{}) (err error) {
err = rpcx.RegisterFunctionName(name, fn)
return
}
//同步 执行目标远程服务方法
func (this *RPCXService) RpcCallById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error) {
defer lego.Recover(fmt.Sprintf("RpcCallById sId:%s rkey:%v arg %v", sId, serviceMethod, args))
this.lock.RLock()
defer this.lock.RUnlock()
ss, ok := this.serverList.Load(sId)
if !ok {
if node, err := registry.GetServiceById(sId); err != nil {
log.Errorf("未找到目标服务【%s】节点 err:%v", sId, err)
return fmt.Errorf("No Found " + sId)
} else {
ss, err = NewServiceSession(node)
if err != nil {
return fmt.Errorf(fmt.Sprintf("创建服务会话失败【%s】 err:%v", sId, err))
} else {
this.serverList.Store(node.Id, ss)
}
}
}
err = ss.(base.IRPCXServiceSession).Call(ctx, serviceMethod, args, reply)
return
}
//异步 执行目标远程服务方法
func (this *RPCXService) RpcGoById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error) {
defer lego.Recover(fmt.Sprintf("RpcGoById sId:%s rkey:%v arg %v", sId, serviceMethod, args))
this.lock.RLock()
defer this.lock.RUnlock()
ss, ok := this.serverList.Load(sId)
if !ok {
if node, err := registry.GetServiceById(sId); err != nil {
log.Errorf("未找到目标服务【%s】节点 err:%v", sId, err)
return nil, fmt.Errorf("No Found " + sId)
} else {
ss, err = NewServiceSession(node)
if err != nil {
return nil, fmt.Errorf(fmt.Sprintf("创建服务会话失败【%s】 err:%v", sId, err))
} else {
this.serverList.Store(node.Id, ss)
}
}
}
call, err = ss.(base.IRPCXServiceSession).Go(ctx, serviceMethod, args, reply)
return
}
func (this *RPCXService) RpcCallByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error) {
defer lego.Recover(fmt.Sprintf("RpcCallByType sType:%s rkey:%s arg %v", sType, serviceMethod, args))
this.lock.RLock()
defer this.lock.RUnlock()
ss, err := this.rpcxService.DefauleRpcRouteRules(sType, core.AutoIp)
if err != nil {
log.Errorf("未找到目标服务【%s】节点 err:%v", sType, err)
return err
}
err = ss.Call(ctx, serviceMethod, args, reply)
return
}
func (this *RPCXService) RpcGoByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error) {
defer lego.Recover(fmt.Sprintf("RpcCallByType sType:%s rkey:%s arg %v", sType, serviceMethod, args))
this.lock.RLock()
defer this.lock.RUnlock()
ss, err := this.rpcxService.DefauleRpcRouteRules(sType, core.AutoIp)
if err != nil {
log.Errorf("未找到目标服务【%s】节点 err:%v", sType, err)
return nil, err
}
call, err = ss.Go(ctx, serviceMethod, args, reply)
return
}

View File

@ -0,0 +1,64 @@
package rpcx
import (
"context"
"fmt"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/sys/registry"
"go_dreamfactory/lego/sys/rpcx"
"github.com/smallnest/rpcx/client"
)
func NewServiceSession(node *registry.ServiceNode) (ss base.IRPCXServiceSession, err error) {
session := new(ServiceSession)
session.node = node
session.client, err = rpcx.NewRpcClient(fmt.Sprintf("%s:%d", node.IP, node.Port), node.Id)
ss = session
return
}
type ServiceSession struct {
node *registry.ServiceNode
client rpcx.IRPCXClient
}
func (this *ServiceSession) GetId() string {
return this.node.Id
}
func (this *ServiceSession) GetIp() string {
return this.node.IP
}
func (this *ServiceSession) GetRpcId() string {
return this.node.RpcId
}
func (this *ServiceSession) GetType() string {
return this.node.Type
}
func (this *ServiceSession) GetVersion() string {
return this.node.Version
}
func (this *ServiceSession) SetVersion(v string) {
this.node.Version = v
}
func (this *ServiceSession) GetPreWeight() float64 {
return this.node.PreWeight
}
func (this *ServiceSession) SetPreWeight(p float64) {
this.node.PreWeight = p
}
func (this *ServiceSession) Done() {
this.client.Stop()
}
func (this *ServiceSession) Call(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) error {
return this.client.Call(ctx, serviceMethod, args, reply)
}
func (this *ServiceSession) Go(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) (*client.Call, error) {
return this.client.Go(ctx, serviceMethod, args, reply, nil)
}

View File

@ -0,0 +1,58 @@
package cbase
import (
"go_dreamfactory/lego/core"
)
type ModuleBase struct {
comps []core.IModuleComp
}
func (this *ModuleBase) NewOptions() (options core.IModuleOptions) {
return new(ModuleOptions)
}
func (this *ModuleBase) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) {
module.OnInstallComp()
for _, v := range this.comps {
err = v.Init(service, module, v, options)
if err != nil {
return
}
}
return
}
func (this *ModuleBase) OnInstallComp() {
}
func (this *ModuleBase) Start() (err error) {
for _, v := range this.comps {
err = v.Start()
if err != nil {
return
}
}
return
}
func (this *ModuleBase) Run(closeSig chan bool) (err error) {
return
}
func (this *ModuleBase) Destroy() (err error) {
for _, v := range this.comps {
err = v.Destroy()
if err != nil {
return
}
}
return
}
func (this *ModuleBase) RegisterComp(comp core.IModuleComp) interface{} {
this.comps = append(this.comps, comp)
return comp
}

View File

@ -0,0 +1,19 @@
package cbase
import (
"go_dreamfactory/lego/core"
)
type ModuleCompBase struct{}
func (this *ModuleCompBase) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
return
}
func (this *ModuleCompBase) Start() (err error) {
return
}
func (this *ModuleCompBase) Destroy() (err error) {
return
}

View File

@ -0,0 +1,13 @@
package cbase
import "go_dreamfactory/lego/utils/mapstructure"
type ModuleOptions struct {
}
func (this *ModuleOptions) LoadConfig(settings map[string]interface{}) (err error) {
if settings != nil {
mapstructure.Decode(settings, &this)
}
return
}

View File

@ -0,0 +1,177 @@
package cbase
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"go_dreamfactory/lego"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
)
type defaultModule struct {
seetring map[string]interface{}
mi core.IModule
closeSig chan bool
wg sync.WaitGroup
}
func (this *defaultModule) run() {
this.mi.Run(this.closeSig)
this.wg.Done()
}
func (this *defaultModule) destroy() (err error) {
defer lego.Recover(fmt.Sprintf("Module :%s destroy", this.mi.GetType()))
err = this.mi.Destroy()
if err != nil {
err = fmt.Errorf("关闭模块【%s】失败 err:%s", this.mi.GetType(), err.Error())
}
return
}
type ServiceBase struct {
closesig chan string
Service core.IService
comps map[core.S_Comps]core.IServiceComp
modules map[core.M_Modules]*defaultModule
}
func (this *ServiceBase) Init(service core.IService) (err error) {
this.closesig = make(chan string, 1)
this.Service = service
this.modules = make(map[core.M_Modules]*defaultModule)
this.Service.InitSys()
for _, v := range this.comps {
options := v.NewOptions()
if o, ok := service.GetSettings().Comps[string(v.GetName())]; ok {
options.LoadConfig(o)
}
err = v.Init(this.Service, v, options)
if err != nil {
return
}
}
log.Infof("服务[%s] 初始化完成!", this.Service.GetId())
return nil
}
//配置服务组件
func (this *ServiceBase) OnInstallComp(cops ...core.IServiceComp) {
this.comps = make(map[core.S_Comps]core.IServiceComp)
for _, v := range cops {
if _, ok := this.comps[v.GetName()]; ok {
log.Errorf("覆盖注册组件【%s】", v.GetName())
}
this.comps[v.GetName()] = v
}
}
func (this *ServiceBase) Start() (err error) {
for _, v := range this.comps {
err = v.Start()
if err != nil {
return
}
}
log.Infof("服务[%s:%s] 启动完成!", this.Service.GetId(), this.Service.GetVersion())
return
}
func (this *ServiceBase) Run(mod ...core.IModule) {
for _, v := range mod {
if sf, ok := this.Service.GetSettings().Modules[string(v.GetType())]; ok {
this.modules[v.GetType()] = &defaultModule{
seetring: sf,
mi: v,
closeSig: make(chan bool, 1),
}
} else {
this.modules[v.GetType()] = &defaultModule{
seetring: make(map[string]interface{}),
mi: v,
closeSig: make(chan bool, 1),
}
log.Warnf("注册模块【%s】 没有对应的配置信息", v.GetType())
}
}
for _, v := range this.modules {
options := v.mi.NewOptions()
if err := options.LoadConfig(v.seetring); err == nil {
err := v.mi.Init(this.Service, v.mi, options)
if err != nil {
log.Panicf(fmt.Sprintf("初始化模块【%s】错误 err:%v", v.mi.GetType(), err))
}
} else {
log.Panicf(fmt.Sprintf("模块【%s】 Options:%v 配置错误 err:%v", v.mi.GetType(), v.seetring, err))
}
}
for _, v := range this.modules {
err := v.mi.Start()
if err != nil {
log.Panicf(fmt.Sprintf("启动模块【%s】错误 err:%v", v.mi.GetType(), err))
}
}
for _, v := range this.modules {
v.wg.Add(1)
go v.run()
}
event.TriggerEvent(core.Event_ServiceStartEnd) //广播事件
//监听外部关闭服务信号
c := make(chan os.Signal, 1)
//添加进程结束信号
signal.Notify(c,
os.Interrupt, //退出信号 ctrl+c退出
os.Kill, //kill 信号
syscall.SIGHUP, //终端控制进程结束(终端连接断开)
syscall.SIGINT, //用户发送INTR字符(Ctrl+C)触发
syscall.SIGTERM, //结束程序(可以被捕获、阻塞或忽略)
syscall.SIGQUIT) //用户发送QUIT字符(Ctrl+/)触发
select {
case sig := <-c:
log.Errorf("服务[%s] 关闭 signal = %v\n", this.Service.GetId(), sig)
case <-this.closesig:
log.Errorf("服务[%s] 关闭\n", this.Service.GetId())
}
}
func (this *ServiceBase) Close(closemsg string) {
this.closesig <- closemsg
}
func (this *ServiceBase) Destroy() (err error) {
for _, v := range this.modules {
v.closeSig <- true
v.wg.Wait()
err = v.destroy()
if err != nil {
return
}
}
for _, v := range this.comps {
err = v.Destroy()
if err != nil {
return
}
}
return
}
func (this *ServiceBase) GetModule(ModuleName core.M_Modules) (module core.IModule, err error) {
if v, ok := this.modules[ModuleName]; ok {
return v.mi, nil
} else {
return nil, fmt.Errorf("未装配模块【%s】", ModuleName)
}
}
func (this *ServiceBase) GetComp(CompName core.S_Comps) (comp core.IServiceComp, err error) {
if v, ok := this.comps[CompName]; ok {
return v, nil
} else {
return nil, fmt.Errorf("Service 未装配组件【%s】", CompName)
}
}

View File

@ -0,0 +1,24 @@
package cbase
import (
"go_dreamfactory/lego/core"
)
type ServiceCompBase struct {
}
func (this *ServiceCompBase) NewOptions() (options core.ICompOptions) {
return new(ServiceCompOptions)
}
func (this *ServiceCompBase) Init(service core.IService, comp core.IServiceComp, options core.ICompOptions) (err error) {
return
}
func (this *ServiceCompBase) Start() (err error) {
return
}
func (this *ServiceCompBase) Destroy() (err error) {
return
}

View File

@ -0,0 +1,17 @@
package cbase
import (
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/utils/mapstructure"
)
type ServiceCompOptions struct {
core.ICompOptions
}
func (this *ServiceCompOptions) LoadConfig(settings map[string]interface{}) (err error) {
if settings != nil {
mapstructure.Decode(settings, &this)
}
return
}

140
lego/core/core.go Normal file
View File

@ -0,0 +1,140 @@
package core
type S_Category string //服务类别 例如 网关服务 游戏服务 业务服务 主要用于服务功能分类
type M_Modules string //模块类型
type S_Comps string //服务器组件类型
type ErrorCode int32 //错误码
type Event_Key string //事件Key
type Rpc_Key string //RPC
type Redis_Key string //Redis缓存
type SqlTable string //数据库表定义
type CustomRoute uint8 //自定义网关
const (
AutoIp = "0.0.0.0"
AllIp = "255.255.255.255"
)
const ( //默认事件
Event_ServiceStartEnd Event_Key = "ServiceStartEnd" //服务完全启动完毕
Event_FindNewService Event_Key = "FindNewService" //发现新的服务
Event_UpDataOldService Event_Key = "UpDataOldService" //发现新的服务
Event_LoseService Event_Key = "LoseService" //丢失服务
Event_RegistryStart Event_Key = "RegistryStart" //注册表系统启动成功
)
const (
S_Category_SystemService S_Category = "SystemService" //系统服务类型
S_Category_GateService S_Category = "GateService" //网关服务类型
S_Category_BusinessService S_Category = "BusinessService" //业务服务器
)
type ServiceSttings struct {
Id string //服务Id
Type string //服务类型 (相同的服务可以启动多个)
Tag string //服务集群标签 (相同标签的集群服务可以互相发现和发现)
Category S_Category //服务列表 (用于区分集群服务下相似业务功能的服务器 例如:游戏服务器)
Ip string //服务所在Ip ()
Port int //服务rpcx监听端口
Comps map[string]map[string]interface{} //服务组件配置
Sys map[string]map[string]interface{} //服务系统配置
Modules map[string]map[string]interface{} //服务模块配置
}
type IService interface {
GetId() string //获取服务id
GetType() string //获取服务类型
GetVersion() string //获取服务版本
GetIp() string //获取服务器运ip
GetPort() int //服务默认端口
GetSettings() ServiceSttings //获取服务配置表信息
Init(service IService) (err error) //初始化接口
InitSys() //初始化系统
OnInstallComp(cops ...IServiceComp) //组装服务组件
Start() (err error) //启动服务
Run(mods ...IModule) //运行服务
Close(closemsg string) //关闭服务
Destroy() (err error) //销毁服务
GetComp(CompName S_Comps) (comp IServiceComp, err error) //获取组件
GetModule(ModuleName M_Modules) (module IModule, err error) //获取模块
}
type IServiceComp interface {
GetName() S_Comps
NewOptions() (options ICompOptions)
Init(service IService, comp IServiceComp, options ICompOptions) (err error)
Start() (err error)
Destroy() (err error)
}
type IModule interface {
GetType() M_Modules
NewOptions() (options IModuleOptions)
Init(service IService, module IModule, options IModuleOptions) (err error)
OnInstallComp()
Start() (err error)
Run(closeSig chan bool) (err error)
Destroy() (err error)
}
type ICompOptions interface {
LoadConfig(settings map[string]interface{}) (err error)
}
type IModuleOptions interface {
LoadConfig(settings map[string]interface{}) (err error)
}
type IModuleComp interface {
Init(service IService, module IModule, comp IModuleComp, options IModuleOptions) (err error)
Start() (err error)
Destroy() (err error)
}
type IUserSession interface {
GetSessionId() string
GetIP() string
GetGateId() string
SendMsg(comdId uint16, msgId uint16, msg interface{}) (err error)
Close() (err error)
}
type IServiceMonitor interface {
IModule
RegisterServiceSettingItem(comp S_Comps, name string, iswrite bool, value interface{}, f func(newvalue string) (err error)) //注册服务级别的Setting
RegisterModuleSettingItem(module M_Modules, name string, iswrite bool, value interface{}, f func(newvalue string) (err error)) //注册模块级别的Setting
}
//Monitor 数据
type (
SettingItem struct {
ItemName string
IsWrite bool
Data interface{}
}
ServiceMonitor struct { //服务监听
ServiceId string //服务Id
ServiceType string //服务类型
ServiceCategory S_Category //服务列表
ServiceVersion string //服务版本
ServiceTag string //服务集群
Pid int32 //进程Id
Pname string //进程名称
MemoryUsed float64 //内存使用量
CpuUsed float64 //Cpu使用量
TotalGoroutine int //总的协程数
CurrPreWeight float64 //服务权重
CompsSetting map[S_Comps]*CompsSetting //服务器配置信息
SysSetting map[string]*SysSetting //服务器系统配置信息
ModuleMonitor map[M_Modules]*ModuleMonitor //模块监听信息
}
CompsSetting struct { //模块监听
CompName string //系统名称
Setting map[string]*SettingItem //系统配置信息
}
SysSetting struct { //模块监听
SysName string //系统名称
Setting map[string]*SettingItem //系统配置信息
}
ModuleMonitor struct { //模块监听
ModuleName M_Modules //模块名称
Setting map[string]*SettingItem //模块配置信息
}
)

41
lego/core/errorcode.go Normal file
View File

@ -0,0 +1,41 @@
package core
import "fmt"
///内置错误码 0-1000 请外部应用服务不要占用
const (
ErrorCode_Success ErrorCode = 0 //成功
ErrorCode_NoFindService ErrorCode = 10 //没有找到远程服务器
ErrorCode_RpcFuncExecutionError ErrorCode = 11 //Rpc方法执行错误
ErrorCode_CacheReadError ErrorCode = 12 //缓存读取失败
ErrorCode_SqlExecutionError ErrorCode = 13 //数据库执行错误
ErrorCode_ReqParameterError ErrorCode = 14 //请求参数错误
ErrorCode_SignError ErrorCode = 15 //签名错误
ErrorCode_InsufficientPermissions ErrorCode = 16 //权限不足
ErrorCode_NoLogin ErrorCode = 17 //未登录
//gate
ErrorCode_NoRoute ErrorCode = 201 //没有路由
ErrorCode_LocalRouteExecutionError ErrorCode = 202 //本地路由执行错误
)
var ErrorCodeMsg = map[ErrorCode]string{
ErrorCode_Success: "成功",
ErrorCode_NoFindService: "没有找到远程服务器",
ErrorCode_RpcFuncExecutionError: "Rpc方法执行错误",
ErrorCode_CacheReadError: "缓存读取失败",
ErrorCode_SqlExecutionError: "数据库执行错误",
ErrorCode_ReqParameterError: "请求参数错误",
ErrorCode_SignError: "签名错误",
ErrorCode_InsufficientPermissions: "权限不足",
ErrorCode_NoLogin: "未登录",
ErrorCode_NoRoute: "没有路由",
ErrorCode_LocalRouteExecutionError: "本地路由执行错误",
}
func GetErrorCodeMsg(code ErrorCode) string {
if v, ok := ErrorCodeMsg[code]; ok {
return v
} else {
return fmt.Sprintf("ErrorCode:%d", code)
}
}

37
lego/lego.go Normal file
View File

@ -0,0 +1,37 @@
package lego
import (
"runtime"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/log"
)
//启动服务
func Run(service core.IService, mod ...core.IModule) {
cpuNum := runtime.NumCPU() //获得当前设备的cpu核心数
runtime.GOMAXPROCS(cpuNum) //设置需要用到的cpu数量
err := service.Init(service)
if err != nil {
log.Panicf("服务初始化失败 err=%s", err.Error())
}
err = service.Start()
if err != nil {
log.Panicf("服务启动失败 err=%s", err.Error())
}
service.Run(mod...)
err = service.Destroy()
if err != nil {
log.Panicf("服务销毁失败 err=%s", err.Error())
}
log.Infof("服务【%s】关闭成功", service.GetId())
}
//错误采集
func Recover(tag string) {
if r := recover(); r != nil {
buf := make([]byte, 1024)
l := runtime.Stack(buf, false)
log.Errorf("%s - %v: %s", tag, r, buf[:l])
}
}

View File

@ -0,0 +1,134 @@
package blockcache
import (
"sync"
"sync/atomic"
"unsafe"
"go_dreamfactory/lego/utils/container"
)
func newSys(options Options) (sys *Cache, err error) {
sys = &Cache{
options: options,
inpip: make(chan interface{}),
outpip: make(chan interface{}),
outnotic: make(chan struct{}),
element: container.NewLKQueue(),
free: options.CacheMaxSzie,
}
go sys.run()
return
}
type Item struct {
Size int64
Value interface{}
}
type Cache struct {
options Options
inpip chan interface{}
outpip chan interface{}
outnotic chan struct{}
instate int32
outruning int32
element *container.LKQueue
free int64
close int32
wg sync.WaitGroup
}
func (this *Cache) In() chan<- interface{} {
return this.inpip
}
func (this *Cache) Out() <-chan interface{} {
return this.outpip
}
func (this *Cache) Close() {
atomic.StoreInt32(&this.close, 1)
close(this.inpip)
close(this.outnotic)
this.wg.Wait()
close(this.outpip)
}
func (this *Cache) run() {
for v := range this.inpip {
siez := int64(unsafe.Sizeof(v))
if siez > this.options.CacheMaxSzie { //异常数据
this.Errorf("item size:%d large CacheMaxSzie:%d", siez, this.options.CacheMaxSzie)
continue
} else if siez > atomic.LoadInt64(&this.free) { //空间不足
atomic.StoreInt32(&this.instate, 1)
locp:
for _ = range this.outnotic {
if siez > atomic.LoadInt64(&this.free) {
atomic.StoreInt32(&this.instate, 1)
} else {
this.element.Enqueue(&Item{Size: siez, Value: v})
atomic.AddInt64(&this.free, -1*siez)
break locp
}
}
} else {
this.element.Enqueue(&Item{Size: siez, Value: v})
atomic.AddInt64(&this.free, -1*siez)
}
if atomic.CompareAndSwapInt32(&this.outruning, 0, 1) {
this.wg.Add(1)
go func() {
locp:
for {
v := this.element.Dequeue()
if v != nil && atomic.LoadInt32(&this.close) == 0 {
item := v.(*Item)
atomic.AddInt64(&this.free, item.Size)
if atomic.CompareAndSwapInt32(&this.instate, 1, 0) {
this.outnotic <- struct{}{}
}
this.outpip <- item.Value
} else {
break locp
}
}
atomic.StoreInt32(&this.outruning, 0)
this.wg.Done()
}()
}
}
}
///日志***********************************************************************
func (this *Cache) Debugf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Debugf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Infof(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Infof("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Warnf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Warnf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Errorf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Errorf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Panicf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Panicf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Fatalf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Fatalf("[SYS BlockCache] "+format, a)
}
}

View File

@ -0,0 +1,44 @@
package blockcache
/*
限容堵塞缓冲池系统
设置最大内存大小 当缓存区为存满是直接写入 写满后进入堵塞状态 等待缓存区释放
*/
type (
ISys interface {
In() chan<- interface{}
Out() <-chan interface{}
Close()
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
if defsys, err = newSys(newOptions(config, option...)); err == nil {
}
return
}
func NewSys(option ...Option) (sys ISys, err error) {
if sys, err = newSys(newOptionsByOption(option...)); err == nil {
}
return
}
func In() chan<- interface{} {
return defsys.In()
}
func Out() <-chan interface{} {
return defsys.Out()
}
func Close() {
defsys.Close()
}

View File

@ -0,0 +1,57 @@
package blockcache
import (
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
CacheMaxSzie int64
Debug bool //日志是否开启
Log log.ILog
}
func SetCacheMaxSzie(v int64) Option {
return func(o *Options) {
o.CacheMaxSzie = v
}
}
func SetDebug(v bool) Option {
return func(o *Options) {
o.Debug = v
}
}
func SetLog(v log.ILog) Option {
return func(o *Options) {
o.Log = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
CacheMaxSzie: 1024 * 1024 * 100,
Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
CacheMaxSzie: 1024 * 1024 * 100,
Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,58 @@
package blockcache_test
import (
"fmt"
"os"
"os/signal"
"syscall"
"testing"
"time"
"go_dreamfactory/lego/sys/blockcache"
"go_dreamfactory/lego/sys/log"
)
func Test_sys(t *testing.T) {
if err := log.OnInit(nil, log.SetLoglevel(log.DebugLevel), log.SetDebugMode(true)); err != nil {
fmt.Printf("log init err:%v", err)
return
}
log.Debugf("log init succ")
if sys, err := blockcache.NewSys(blockcache.SetCacheMaxSzie(100)); err != nil {
log.Debugf("livego init err:%v", err)
return
} else {
closeSignal := make(chan struct{})
go func() {
locp:
for {
select {
case <-closeSignal:
break locp
default:
sys.In() <- "liwei1dao"
log.Debugf("In:liwei1dao")
}
}
log.Debugf("In:End")
}()
go func() {
for v := range sys.Out() {
log.Debugf("Out:%v", v)
time.Sleep(time.Second)
}
log.Debugf("Out:End")
}()
go func() {
time.Sleep(time.Second * 3)
closeSignal <- struct{}{}
sys.Close()
}()
}
sigterm := make(chan os.Signal, 1)
signal.Notify(sigterm, syscall.SIGINT, syscall.SIGTERM)
select {
case <-sigterm:
fmt.Printf("terminating: via signal\n")
}
}

820
lego/sys/cachego/cache.go Normal file
View File

@ -0,0 +1,820 @@
package cachego
import (
"encoding/gob"
"fmt"
"io"
"os"
"time"
)
func (this *CacheGo) SetDefault(k string, x interface{}) {
this.Set(k, x, this.options.Expiration)
}
func (this *CacheGo) Replace(k string, x interface{}, d time.Duration) error {
this.mu.Lock()
_, found := this.get(k)
if !found {
this.mu.Unlock()
return fmt.Errorf("Item %s doesn't exist", k)
}
this.set(k, x, d)
this.mu.Unlock()
return nil
}
func (this *CacheGo) GetWithExpiration(k string) (interface{}, time.Time, bool) {
this.mu.RLock()
// "Inlining" of get and Expired
item, found := this.items[k]
if !found {
this.mu.RUnlock()
return nil, time.Time{}, false
}
if item.Expiration > 0 {
if time.Now().UnixNano() > item.Expiration {
this.mu.RUnlock()
return nil, time.Time{}, false
}
// Return the item and the expiration time
this.mu.RUnlock()
return item.Object, time.Unix(0, item.Expiration), true
}
// If expiration <= 0 (i.e. no expiration time set) then return the item
// and a zeroed time.Time
this.mu.RUnlock()
return item.Object, time.Time{}, true
}
func (this *CacheGo) Increment(k string, n int64) error {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return fmt.Errorf("Item %s not found", k)
}
switch v.Object.(type) {
case int:
v.Object = v.Object.(int) + int(n)
case int8:
v.Object = v.Object.(int8) + int8(n)
case int16:
v.Object = v.Object.(int16) + int16(n)
case int32:
v.Object = v.Object.(int32) + int32(n)
case int64:
v.Object = v.Object.(int64) + n
case uint:
v.Object = v.Object.(uint) + uint(n)
case uintptr:
v.Object = v.Object.(uintptr) + uintptr(n)
case uint8:
v.Object = v.Object.(uint8) + uint8(n)
case uint16:
v.Object = v.Object.(uint16) + uint16(n)
case uint32:
v.Object = v.Object.(uint32) + uint32(n)
case uint64:
v.Object = v.Object.(uint64) + uint64(n)
case float32:
v.Object = v.Object.(float32) + float32(n)
case float64:
v.Object = v.Object.(float64) + float64(n)
default:
this.mu.Unlock()
return fmt.Errorf("The value for %s is not an integer", k)
}
this.items[k] = v
this.mu.Unlock()
return nil
}
func (this *CacheGo) IncrementFloat(k string, n float64) error {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return fmt.Errorf("Item %s not found", k)
}
switch v.Object.(type) {
case float32:
v.Object = v.Object.(float32) + float32(n)
case float64:
v.Object = v.Object.(float64) + n
default:
this.mu.Unlock()
return fmt.Errorf("The value for %s does not have type float32 or float64", k)
}
this.items[k] = v
this.mu.Unlock()
return nil
}
func (this *CacheGo) IncrementInt(k string, n int) (int, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementInt8(k string, n int8) (int8, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int8)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int8", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementInt16(k string, n int16) (int16, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int16)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int16", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementInt32(k string, n int32) (int32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int32", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementInt64(k string, n int64) (int64, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int64)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int64", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUint(k string, n uint) (uint, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUintptr(k string, n uintptr) (uintptr, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uintptr)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uintptr", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUint8(k string, n uint8) (uint8, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint8)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint8", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUint16(k string, n uint16) (uint16, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint16)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint16", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUint32(k string, n uint32) (uint32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint32", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementUint64(k string, n uint64) (uint64, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint64)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint64", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementFloat32(k string, n float32) (float32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(float32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an float32", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) IncrementFloat64(k string, n float64) (float64, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(float64)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an float64", k)
}
nv := rv + n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) Decrement(k string, n int64) error {
// TODO: Implement Increment and Decrement more cleanly.
// (Cannot do Increment(k, n*-1) for uints.)
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return fmt.Errorf("Item not found")
}
switch v.Object.(type) {
case int:
v.Object = v.Object.(int) - int(n)
case int8:
v.Object = v.Object.(int8) - int8(n)
case int16:
v.Object = v.Object.(int16) - int16(n)
case int32:
v.Object = v.Object.(int32) - int32(n)
case int64:
v.Object = v.Object.(int64) - n
case uint:
v.Object = v.Object.(uint) - uint(n)
case uintptr:
v.Object = v.Object.(uintptr) - uintptr(n)
case uint8:
v.Object = v.Object.(uint8) - uint8(n)
case uint16:
v.Object = v.Object.(uint16) - uint16(n)
case uint32:
v.Object = v.Object.(uint32) - uint32(n)
case uint64:
v.Object = v.Object.(uint64) - uint64(n)
case float32:
v.Object = v.Object.(float32) - float32(n)
case float64:
v.Object = v.Object.(float64) - float64(n)
default:
this.mu.Unlock()
return fmt.Errorf("The value for %s is not an integer", k)
}
this.items[k] = v
this.mu.Unlock()
return nil
}
func (this *CacheGo) DecrementFloat(k string, n float64) error {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return fmt.Errorf("Item %s not found", k)
}
switch v.Object.(type) {
case float32:
v.Object = v.Object.(float32) - float32(n)
case float64:
v.Object = v.Object.(float64) - n
default:
this.mu.Unlock()
return fmt.Errorf("The value for %s does not have type float32 or float64", k)
}
this.items[k] = v
this.mu.Unlock()
return nil
}
func (this *CacheGo) DecrementInt(k string, n int) (int, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementInt8(k string, n int8) (int8, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int8)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int8", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementInt16(k string, n int16) (int16, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int16)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int16", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementInt32(k string, n int32) (int32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int32", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementInt64(k string, n int64) (int64, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(int64)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an int64", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUint(k string, n uint) (uint, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUintptr(k string, n uintptr) (uintptr, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uintptr)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uintptr", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUint8(k string, n uint8) (uint8, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint8)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint8", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUint16(k string, n uint16) (uint16, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint16)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint16", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUint32(k string, n uint32) (uint32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint32", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementUint64(k string, n uint64) (uint64, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(uint64)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an uint64", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) DecrementFloat32(k string, n float32) (float32, error) {
this.mu.Lock()
v, found := this.items[k]
if !found || v.Expired() {
this.mu.Unlock()
return 0, fmt.Errorf("Item %s not found", k)
}
rv, ok := v.Object.(float32)
if !ok {
this.mu.Unlock()
return 0, fmt.Errorf("The value for %s is not an float32", k)
}
nv := rv - n
v.Object = nv
this.items[k] = v
this.mu.Unlock()
return nv, nil
}
func (this *CacheGo) OnEvicted(f func(string, interface{})) {
this.mu.Lock()
this.onEvicted = f
this.mu.Unlock()
}
func (this *CacheGo) Set(k string, x interface{}, d time.Duration) {
var e int64
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
this.mu.Lock()
this.items[k] = Item{
Object: x,
Expiration: e,
}
this.mu.Unlock()
}
func (this *CacheGo) Add(k string, x interface{}, d time.Duration) error {
this.mu.Lock()
_, found := this.get(k)
if found {
this.mu.Unlock()
return fmt.Errorf("Item %s already exists", k)
}
this.set(k, x, d)
this.mu.Unlock()
return nil
}
func (this *CacheGo) DeleteExpired() {
var evictedItems []keyAndValue
now := time.Now().UnixNano()
this.mu.Lock()
for k, v := range this.items {
// "Inlining" of expired
if v.Expiration > 0 && now > v.Expiration {
ov, evicted := this.delete(k)
if evicted {
evictedItems = append(evictedItems, keyAndValue{k, ov})
}
}
}
this.mu.Unlock()
for _, v := range evictedItems {
this.onEvicted(v.key, v.value)
}
}
func (this *CacheGo) SaveFile(fname string) error {
fp, err := os.Create(fname)
if err != nil {
return err
}
err = this.Save(fp)
if err != nil {
fp.Close()
return err
}
return fp.Close()
}
func (this *CacheGo) Save(w io.Writer) (err error) {
enc := gob.NewEncoder(w)
defer func() {
if x := recover(); x != nil {
err = fmt.Errorf("Error registering item types with Gob library")
}
}()
this.mu.RLock()
defer this.mu.RUnlock()
for _, v := range this.items {
gob.Register(v.Object)
}
err = enc.Encode(&this.items)
return
}
func (this *CacheGo) Load(r io.Reader) error {
dec := gob.NewDecoder(r)
items := map[string]Item{}
err := dec.Decode(&items)
if err == nil {
this.mu.Lock()
defer this.mu.Unlock()
for k, v := range items {
ov, found := this.items[k]
if !found || ov.Expired() {
this.items[k] = v
}
}
}
return err
}
func (this *CacheGo) LoadFile(fname string) error {
fp, err := os.Open(fname)
if err != nil {
return err
}
err = this.Load(fp)
if err != nil {
fp.Close()
return err
}
return fp.Close()
}
func (this *CacheGo) Items() map[string]Item {
this.mu.RLock()
defer this.mu.RUnlock()
m := make(map[string]Item, len(this.items))
now := time.Now().UnixNano()
for k, v := range this.items {
if v.Expiration > 0 {
if now > v.Expiration {
continue
}
}
m[k] = v
}
return m
}
func (this *CacheGo) ItemCount() int {
this.mu.RLock()
n := len(this.items)
this.mu.RUnlock()
return n
}
func (this *CacheGo) Flush() {
this.mu.Lock()
this.items = map[string]Item{}
this.mu.Unlock()
}
func (this *CacheGo) get(k string) (interface{}, bool) {
item, found := this.items[k]
if !found {
return nil, false
}
// "Inlining" of Expired
if item.Expiration > 0 {
if time.Now().UnixNano() > item.Expiration {
return nil, false
}
}
return item.Object, true
}
func (this *CacheGo) set(k string, x interface{}, d time.Duration) {
var e int64
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
this.items[k] = Item{
Object: x,
Expiration: e,
}
}
func (this *CacheGo) delete(k string) (interface{}, bool) {
if this.onEvicted != nil {
if v, found := this.items[k]; found {
delete(this.items, k)
return v.Object, true
}
}
delete(this.items, k)
return nil, false
}

View File

@ -0,0 +1,47 @@
package cachego
import (
"sync"
"time"
)
func newSys(options Options) (sys *CacheGo, err error) {
sys = &CacheGo{
options: options,
items: make(map[string]Item),
}
err = sys.init()
return
}
type CacheGo struct {
options Options
items map[string]Item
mu sync.RWMutex
onEvicted func(string, interface{})
stop chan bool
}
func (this *CacheGo) init() (err error) {
if this.options.CleanupInterval > 0 {
go this.run()
}
return
}
func (this *CacheGo) run() {
ticker := time.NewTicker(time.Duration(this.options.CleanupInterval) * time.Second)
for {
select {
case <-ticker.C:
this.DeleteExpired()
case <-this.stop:
ticker.Stop()
return
}
}
}
func (this *CacheGo) Clsoe() {
this.stop <- true
}

187
lego/sys/cachego/core.go Normal file
View File

@ -0,0 +1,187 @@
package cachego
/*
本地缓存系统
*/
import (
"io"
"time"
)
type (
ISys interface {
Flush()
ItemCount() int
Items() map[string]Item
SaveFile(fname string) error
Save(w io.Writer) (err error)
Load(r io.Reader) error
LoadFile(fname string) error
Add(k string, x interface{}, d time.Duration) error
Set(k string, x interface{}, d time.Duration)
OnEvicted(f func(string, interface{}))
Increment(k string, n int64) error
IncrementFloat(k string, n float64) error
IncrementInt(k string, n int) (int, error)
IncrementInt8(k string, n int8) (int8, error)
IncrementInt16(k string, n int16) (int16, error)
IncrementInt32(k string, n int32) (int32, error)
IncrementInt64(k string, n int64) (int64, error)
IncrementUint(k string, n uint) (uint, error)
IncrementUintptr(k string, n uintptr) (uintptr, error)
IncrementUint8(k string, n uint8) (uint8, error)
IncrementUint16(k string, n uint16) (uint16, error)
IncrementUint32(k string, n uint32) (uint32, error)
IncrementUint64(k string, n uint64) (uint64, error)
IncrementFloat32(k string, n float32) (float32, error)
IncrementFloat64(k string, n float64) (float64, error)
Decrement(k string, n int64) error
DecrementFloat(k string, n float64) error
DecrementInt(k string, n int) (int, error)
DecrementInt8(k string, n int8) (int8, error)
DecrementInt16(k string, n int16) (int16, error)
DecrementInt32(k string, n int32) (int32, error)
DecrementInt64(k string, n int64) (int64, error)
DecrementUint(k string, n uint) (uint, error)
DecrementUintptr(k string, n uintptr) (uintptr, error)
DecrementUint8(k string, n uint8) (uint8, error)
DecrementUint16(k string, n uint16) (uint16, error)
DecrementUint32(k string, n uint32) (uint32, error)
DecrementUint64(k string, n uint64) (uint64, error)
DecrementFloat32(k string, n float32) (float32, error)
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
if defsys, err = newSys(newOptions(config, option...)); err == nil {
}
return
}
func NewSys(option ...Option) (sys ISys, err error) {
if sys, err = newSys(newOptionsByOption(option...)); err == nil {
}
return
}
func Flush() {
defsys.Flush()
}
func ItemCount() int {
return defsys.ItemCount()
}
func Items() map[string]Item {
return defsys.Items()
}
func SaveFile(fname string) error {
return defsys.SaveFile(fname)
}
func Save(w io.Writer) (err error) {
return defsys.Save(w)
}
func Load(r io.Reader) error {
return defsys.Load(r)
}
func LoadFile(fname string) error {
return defsys.LoadFile(fname)
}
func Add(k string, x interface{}, d time.Duration) error {
return defsys.Add(k, x, d)
}
func Set(k string, x interface{}, d time.Duration) {
defsys.Set(k, x, d)
}
func OnEvicted(f func(string, interface{})) {
defsys.OnEvicted(f)
}
func Increment(k string, n int64) error {
return defsys.Increment(k, n)
}
func IncrementFloat(k string, n float64) error {
return defsys.IncrementFloat(k, n)
}
func IncrementInt(k string, n int) (int, error) {
return defsys.IncrementInt(k, n)
}
func IncrementInt8(k string, n int8) (int8, error) {
return defsys.IncrementInt8(k, n)
}
func IncrementInt16(k string, n int16) (int16, error) {
return defsys.IncrementInt16(k, n)
}
func IncrementInt32(k string, n int32) (int32, error) {
return defsys.IncrementInt32(k, n)
}
func IncrementInt64(k string, n int64) (int64, error) {
return defsys.IncrementInt64(k, n)
}
func IncrementUint(k string, n uint) (uint, error) {
return defsys.IncrementUint(k, n)
}
func IncrementUintptr(k string, n uintptr) (uintptr, error) {
return defsys.IncrementUintptr(k, n)
}
func IncrementUint8(k string, n uint8) (uint8, error) {
return defsys.IncrementUint8(k, n)
}
func IncrementUint16(k string, n uint16) (uint16, error) {
return defsys.IncrementUint16(k, n)
}
func IncrementUint32(k string, n uint32) (uint32, error) {
return defsys.IncrementUint32(k, n)
}
func IncrementUint64(k string, n uint64) (uint64, error) {
return defsys.IncrementUint64(k, n)
}
func IncrementFloat32(k string, n float32) (float32, error) {
return defsys.IncrementFloat32(k, n)
}
func IncrementFloat64(k string, n float64) (float64, error) {
return defsys.IncrementFloat64(k, n)
}
func Decrement(k string, n int64) error {
return defsys.Decrement(k, n)
}
func DecrementFloat(k string, n float64) error {
return defsys.DecrementFloat(k, n)
}
func DecrementInt(k string, n int) (int, error) {
return defsys.DecrementInt(k, n)
}
func DecrementInt8(k string, n int8) (int8, error) {
return defsys.DecrementInt8(k, n)
}
func DecrementInt16(k string, n int16) (int16, error) {
return defsys.DecrementInt16(k, n)
}
func DecrementInt32(k string, n int32) (int32, error) {
return defsys.DecrementInt32(k, n)
}
func DecrementInt64(k string, n int64) (int64, error) {
return defsys.DecrementInt64(k, n)
}
func DecrementUint(k string, n uint) (uint, error) {
return defsys.DecrementUint(k, n)
}
func DecrementUintptr(k string, n uintptr) (uintptr, error) {
return defsys.DecrementUintptr(k, n)
}
func DecrementUint8(k string, n uint8) (uint8, error) {
return defsys.DecrementUint8(k, n)
}
func DecrementUint16(k string, n uint16) (uint16, error) {
return defsys.DecrementUint16(k, n)
}
func DecrementUint32(k string, n uint32) (uint32, error) {
return defsys.DecrementUint32(k, n)
}
func DecrementUint64(k string, n uint64) (uint64, error) {
return defsys.DecrementUint64(k, n)
}
func DecrementFloat32(k string, n float32) (float32, error) {
return defsys.DecrementFloat32(k, n)
}

19
lego/sys/cachego/item.go Normal file
View File

@ -0,0 +1,19 @@
package cachego
import "time"
type keyAndValue struct {
key string
value interface{}
}
type Item struct {
Object interface{}
Expiration int64
}
func (item Item) Expired() bool {
if item.Expiration == 0 {
return false
}
return time.Now().UnixNano() > item.Expiration
}

View File

@ -0,0 +1,38 @@
package cachego
import (
"time"
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
Expiration time.Duration
CleanupInterval time.Duration
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
Expiration: -1,
CleanupInterval: 0,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
Expiration: -1,
CleanupInterval: 0,
}
for _, o := range opts {
o(&options)
}
return options
}

48
lego/sys/cron/core.go Normal file
View File

@ -0,0 +1,48 @@
package cron
import (
tcron "github.com/robfig/cron/v3"
)
type (
ISys interface {
Start()
Stop()
AddFunc(spec string, cmd func()) (tcron.EntryID, error)
Remove(id tcron.EntryID)
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
if defsys, err = newSys(newOptions(config, option...)); err == nil {
Start()
}
return
}
func NewSys(option ...Option) (sys ISys, err error) {
if sys, err = newSys(newOptionsByOption(option...)); err == nil {
Start()
}
return
}
func Start() {
defsys.Start()
}
func Stop() {
defsys.Stop()
}
func AddFunc(spec string, cmd func()) (tcron.EntryID, error) {
return defsys.AddFunc(spec, cmd)
}
func Remove(id tcron.EntryID) {
defsys.Remove(id)
}

32
lego/sys/cron/cron.go Normal file
View File

@ -0,0 +1,32 @@
package cron
import (
tcron "github.com/robfig/cron/v3"
)
func newSys(options Options) (sys *Cron, err error) {
parser := tcron.NewParser(tcron.Second | tcron.Minute | tcron.Hour | tcron.Dom | tcron.Month | tcron.Dow | tcron.Descriptor)
sys = &Cron{options: options, cron: tcron.New(tcron.WithParser(parser))}
return
}
type Cron struct {
cron *tcron.Cron
options Options
}
func (this *Cron) Start() {
this.cron.Start()
}
func (this *Cron) Stop() {
this.cron.Stop()
}
func (this *Cron) AddFunc(spec string, cmd func()) (tcron.EntryID, error) {
return this.cron.AddFunc(spec, cmd)
}
func (this *Cron) Remove(id tcron.EntryID) {
this.cron.Remove(id)
}

28
lego/sys/cron/options.go Normal file
View File

@ -0,0 +1,28 @@
package cron
import (
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{}
for _, o := range opts {
o(&options)
}
return options
}

127
lego/sys/cron/sys_test.go Normal file
View File

@ -0,0 +1,127 @@
package cron_test
import (
"fmt"
"testing"
"time"
"go_dreamfactory/lego/sys/cron"
)
// 1. cron表达式格式
// {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
// 2. cron表达式各占位符解释
// {秒数} ==> 允许值范围: 0~59 ,不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每隔1秒钟触发
// "," 代表在指定的秒数触发,比如"0,15,45"代表0秒、15秒和45秒时触发任务
// "-" 代表在指定的范围内触发,比如"25-45"代表从25秒开始触发到45秒结束触发每隔1秒触发1次
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/20"或者"*/20"代表从0秒钟开始每隔20秒钟触发1次即0秒触发1次20秒触发1次40秒触发1次"5/20"代表5秒触发1次25秒触发1次45秒触发1次"10-45/20"代表在[10,45]内步进20秒命中的时间点触发即10秒触发1次30秒触发1次
// {分钟} ==> 允许值范围: 0~59 ,不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每隔1分钟触发
// "," 代表在指定的分钟触发,比如"10,20,40"代表10分钟、20分钟和40分钟时触发任务
// "-" 代表在指定的范围内触发,比如"5-30"代表从5分钟开始触发到30分钟结束触 发每隔1分钟触发
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/25"或者"*/25"代表从0分钟开始每隔25分钟触发1次即0分钟触发1次第25分钟触发1次第50分钟触发1次"5/25"代表5分钟触发1次30分钟触发1次55分钟触发1次"10-45/20"代表在[10,45]内步进20分钟命中的时间点触发即10分钟触发1次30分钟触发1次
// {小时} ==> 允许值范围: 0~23 ,不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每隔1小时触发
// "," 代表在指定的时间点触发,比如"10,20,23"代表10点钟、20点钟和23点触发任务
// "-" 代表在指定的时间段内触发,比如"20-23"代表从20点开始触发到23点结束触发每隔1小时触发
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/1"或者"*/1"代表从0点开始触发每隔1小时触发1次"1/2"代表从1点开始触发以后每隔2小时触发一次"19-20/2"表达式将只在19点触发
// {日期} ==> 允许值范围: 1~31 ,不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每天触发;
// "?" 与{星期}互斥,即意味着若明确指定{星期}触发,则表示{日期}无意义,以免引起 冲突和混乱
// "," 代表在指定的日期触发,比如"1,10,20"代表1号、10号和20号这3天触发
// "-" 代表在指定的日期范围内触发,比如"10-15"代表从10号开始触发到15号结束触发每隔1天触发
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/5"或者"*/5"代表从1号开始触发每隔5天触发1次"10/5"代表从10号开始触发以后每隔5天触发一次"1-10/2"表达式意味着在[1,10]范围内每隔2天触发即1号3号5号7号9号触发
// "L" 如果{日期}占位符如果是"L",即意味着当月的最后一天触发
// "W "意味着在本月内离当天最近的工作日触发所谓最近工作日即当天到工作日的前后最短距离如果当天即为工作日则距离为0所谓本月内的说法就是不能跨月取到最近工作日即使前/后月份的最后一天/第一天确实满足最近工作日;因此,"LW"则意味着本月的最后一个工作日触发,"W"强烈依赖{月份}
// "C" 根据日历触发,由于使用较少,暂时不做解释
// {月份} ==> 允许值范围: 1~12 (JAN-DEC),不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每个月都触发;
// "," 代表在指定的月份触发,比如"1,6,12"代表1月份、6月份和12月份触发任务
// "-" 代表在指定的月份范围内触发,比如"1-6"代表从1月份开始触发到6月份结束触发每隔1个月触发
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/2"或者"*/2"代表从1月份开始触发每隔2个月触发1次"6/6"代表从6月份开始触发以后每隔6个月触发一次"1-6/12"表达式意味着每年1月份触发
// {星期} ==> 允许值范围: 1~7 (SUN-SAT),1代表星期天(一星期的第一天)以此类推7代表星期六(一星期的最后一天)不允许为空值若值不合法调度器将抛出SchedulerException异常
// "*" 代表每星期都触发;
// "?" 与{日期}互斥,即意味着若明确指定{日期}触发,则表示{星期}无意义,以免引起冲突和混乱
// "," 代表在指定的星期约定触发,比如"1,3,5"代表星期天、星期二和星期四触发
// "-" 代表在指定的星期范围内触发,比如"2-4"代表从星期一开始触发到星期三结束触发每隔1天触发
// "/" 代表触发步进(step)"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/3"或者"*/3"代表从星期天开始触发每隔3天触发1次"1-5/2"表达式意味着在[1,5]范围内每隔2天触发即星期天、星期二、星期四触发
// "L" 如果{星期}占位符如果是"L"即意味着星期的的最后一天触发即星期六触发L= 7或者 L = SAT因此"5L"意味着一个月的最后一个星期四触发
// "#" 用来指定具体的周数,"#"前面代表星期,"#"后面代表本月第几周,比如"2#2"表示本月第二周的星期一,"5#3"表示本月第三周的星期四,因此,"5L"这种形式只不过是"#"的特殊形式而已
// "C" 根据日历触发,由于使用较少,暂时不做解释
// {年份} ==> 允许值范围: 1970~2099 ,允许为空若值不合法调度器将抛出SchedulerException异常
// "*"代表每年都触发;
// ","代表在指定的年份才触发,比如"2011,2012,2013"代表2011年、2012年和2013年触发任务
// "-"代表在指定的年份范围内触发,比如"2011-2020"代表从2011年开始触发到2020年结束触发每隔1年触发
// "/"代表触发步进(step)"/"前面的值代表初始值("*"等同"1970"),后面的值代表偏移量,比如"2011/2"或者"*/2"代表从2011年开始触发每隔2年触发1次
// 注意:除了{日期}和{星期}可以使用"?"来实现互斥,表达无意义的信息之外,其他占位符都要具有具体的时间含义,且依赖关系为:年->月->日期(星期)->小时->分钟->秒数
// 3. cron表达式的强大魅力在于灵活的横向和纵向组合以及简单的语法用cron表达式几乎可以写出任何你想要触发的时间点
// 经典案例:
// "30 * * * * ?" 每半分钟触发任务
// "30 10 * * * ?" 每小时的10分30秒触发任务
// "30 10 1 * * ?" 每天1点10分30秒触发任务
// "30 10 1 20 * ?" 每月20号1点10分30秒触发任务
// "30 10 1 20 10 ? *" 每年10月20号1点10分30秒触发任务
// "30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务
// "30 10 1 ? 10 * 2011" 2011年10月每天1点10分30秒触发任务
// "30 10 1 ? 10 SUN 2011" 2011年10月每周日1点10分30秒触发任务
// "15,30,45 * * * * ?" 每15秒30秒45秒时触发任务
// "15-45 * * * * ?" 15到45秒内每秒都触发任务
// "15/5 * * * * ?" 每分钟的每15秒开始触发每隔5秒触发一次
// "15-30/5 * * * * ?" 每分钟的15秒到30秒之间开始触发每隔5秒触发一次
// "0 0/3 * * * ?" 每小时的第0分0秒开始每三分钟触发一次
// "0 15 10 ? * MON-FRI" 星期一到星期五的10点15分0秒触发任务
// "0 15 10 L * ?" 每个月最后一天的10点15分0秒触发任务
// "0 15 10 LW * ?" 每个月最后一个工作日的10点15分0秒触发任务
// "0 15 10 ? * 5L" 每个月最后一个星期四的10点15分0秒触发任务
// "0 15 10 ? * 5#3" 每个月第三周的星期四的10点15分0秒触发任务
// 一些cron表达式案例
// */5 * * * * ? 每隔5秒执行一次
// 0 */1 * * * ? 每隔1分钟执行一次
// 0 0 5-15 * * ? 每天5-15点整点触发
// 0 0/3 * * * ? 每三分钟触发一次
// 0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
// 0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
// 0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
// 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
// 0 0 10,14,16 * * ? 每天上午10点下午2点4点
// 0 0 12 ? * WED 表示每个星期三中午12点
// 0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点
// 0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
// 0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
// 0 0 23 L * ? 每月最后一天23点执行一次
// 0 15 10 L * ? 每月最后一日的上午10:15触发
// 0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
// 0 15 10 * * ? 2005 2005年的每天上午10:15触发
// 0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
// 0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
func Test_sys(t *testing.T) {
if err := cron.OnInit(nil); err == nil {
// AddFunc("@every 1s", func() { //每一秒
// fmt.Printf("@every 1s")
// })
// AddFunc("@every 1m", func() { //每一分
// fmt.Printf("@every 1m")
// })
// AddFunc("@hourly", func() { //每一小时
// fmt.Printf("@hourly")
// })
// AddFunc("@daily", func() { //每天凌晨
// fmt.Printf("@daily")
// })
// AddFunc("@daily", func() { //每天凌晨
// fmt.Printf("@daily")
// })
// AddFunc("*/5 * * * * ?", func() { //每天凌晨
// fmt.Printf("*/5 * * * * ?")
// })
cron.AddFunc("30/59 0/2 * * * ?", func() { //每隔90秒
fmt.Printf("*/5 * * * * ?")
})
}
time.Sleep(time.Minute * 5)
}

55
lego/sys/event/core.go Normal file
View File

@ -0,0 +1,55 @@
package event
import (
"reflect"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/log"
)
type (
FunctionInfo struct {
Function reflect.Value
Goroutine bool
}
ISys interface {
Register(eId core.Event_Key, f interface{}) (err error)
RegisterGO(eId core.Event_Key, f interface{}) (err error)
RemoveEvent(eId core.Event_Key, f interface{}) (err error)
TriggerEvent(eId core.Event_Key, agr ...interface{})
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func Register(eId core.Event_Key, f interface{}) (err error) {
return defsys.Register(eId, f)
}
func RegisterGO(eId core.Event_Key, f interface{}) (err error) {
return defsys.Register(eId, f)
}
func RemoveEvent(eId core.Event_Key, f interface{}) (err error) {
return defsys.RemoveEvent(eId, f)
}
func TriggerEvent(eId core.Event_Key, agr ...interface{}) {
if defsys != nil {
defsys.TriggerEvent(eId, agr...)
} else {
log.Warnf("event no start")
}
}

89
lego/sys/event/event.go Normal file
View File

@ -0,0 +1,89 @@
package event
import (
"fmt"
"reflect"
"go_dreamfactory/lego"
"go_dreamfactory/lego/core"
)
func newSys(options Options) (sys *EventSys, err error) {
sys = &EventSys{
functions: make(map[core.Event_Key][]*FunctionInfo),
}
return
}
type EventSys struct {
functions map[core.Event_Key][]*FunctionInfo
}
func (this *EventSys) Register(eId core.Event_Key, f interface{}) (err error) {
if _, ok := this.functions[eId]; !ok {
this.functions[eId] = []*FunctionInfo{}
}
if this.checkIsRegister(eId, f) {
return fmt.Errorf("Register the same event repeatedly [%s] method", eId)
}
this.functions[eId] = append(this.functions[eId], &FunctionInfo{
Function: reflect.ValueOf(f),
Goroutine: false,
})
return
}
func (this *EventSys) RegisterGO(eId core.Event_Key, f interface{}) (err error) {
if _, ok := this.functions[eId]; !ok {
this.functions[eId] = []*FunctionInfo{}
}
if this.checkIsRegister(eId, f) {
return fmt.Errorf("Register the same event repeatedly [%s] method", eId)
}
this.functions[eId] = append(this.functions[eId], &FunctionInfo{
Function: reflect.ValueOf(f),
Goroutine: true,
})
return
}
func (this *EventSys) checkIsRegister(eId core.Event_Key, f interface{}) bool {
if _, ok := this.functions[eId]; !ok {
return false
}
for _, v := range this.functions[eId] {
if v.Function == reflect.ValueOf(f) {
return true
}
}
return false
}
//移除事件
func (this *EventSys) RemoveEvent(eId core.Event_Key, f interface{}) (err error) {
for i, v := range this.functions[eId] {
if v.Function == reflect.ValueOf(f) {
this.functions[eId] = append(this.functions[eId][0:i], this.functions[eId][i+1:]...)
return
}
}
return fmt.Errorf("Unregistered [%s] event", eId)
}
//触发
func (this *EventSys) TriggerEvent(eId core.Event_Key, agr ...interface{}) {
defer lego.Recover(fmt.Sprintf("event TriggerEvent:%s", eId))
if v, ok := this.functions[eId]; ok {
for _, f := range v {
in := make([]reflect.Value, len(agr))
for j, a := range agr {
in[j] = reflect.ValueOf(a)
}
if f.Goroutine {
go f.Function.Call(in)
} else {
f.Function.Call(in)
}
}
}
}

28
lego/sys/event/options.go Normal file
View File

@ -0,0 +1,28 @@
package event
import (
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,18 @@
package event_test
import (
"fmt"
"testing"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/event"
)
func Test_sys(t *testing.T) {
if err := event.OnInit(nil); err == nil {
event.Register(core.Event_Key("TestEvent"), func() {
fmt.Printf("TestEvent TriggerEvent")
})
event.TriggerEvent(core.Event_Key("TestEvent"))
}
}

View File

@ -0,0 +1,73 @@
package binding
import "net/http"
// Content-Type MIME of the most common data formats.
const (
MIMEJSON = "application/json"
MIMEHTML = "text/html"
MIMEXML = "application/xml"
MIMEXML2 = "text/xml"
MIMEPlain = "text/plain"
MIMEPOSTForm = "application/x-www-form-urlencoded"
MIMEMultipartPOSTForm = "multipart/form-data"
MIMEPROTOBUF = "application/x-protobuf"
MIMEMSGPACK = "application/x-msgpack"
MIMEMSGPACK2 = "application/msgpack"
MIMEYAML = "application/x-yaml"
)
type Binding interface {
Name() string
Bind(*http.Request, interface{}) error
}
type StructValidator interface {
ValidateStruct(interface{}) error
Engine() interface{}
}
var Validator StructValidator = &defaultValidator{}
var (
JSON = jsonBinding{}
XML = xmlBinding{}
Form = formBinding{}
Query = queryBinding{}
FormPost = formPostBinding{}
FormMultipart = formMultipartBinding{}
ProtoBuf = protobufBinding{}
MsgPack = msgpackBinding{}
YAML = yamlBinding{}
Uri = uriBinding{}
Header = headerBinding{}
)
func Default(method, contentType string) Binding {
if method == http.MethodGet {
return Form
}
switch contentType {
case MIMEJSON:
return JSON
case MIMEXML, MIMEXML2:
return XML
case MIMEPROTOBUF:
return ProtoBuf
case MIMEMSGPACK, MIMEMSGPACK2:
return MsgPack
case MIMEYAML:
return YAML
case MIMEMultipartPOSTForm:
return FormMultipart
default: // case MIMEPOSTForm:
return Form
}
}
func validate(obj interface{}) error {
if Validator == nil {
return nil
}
return Validator.ValidateStruct(obj)
}

View File

@ -0,0 +1,97 @@
// Copyright 2017 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"fmt"
"reflect"
"strings"
"sync"
"github.com/go-playground/validator/v10"
)
type defaultValidator struct {
once sync.Once
validate *validator.Validate
}
type SliceValidationError []error
// Error concatenates all error elements in SliceValidationError into a single string separated by \n.
func (err SliceValidationError) Error() string {
n := len(err)
switch n {
case 0:
return ""
default:
var b strings.Builder
if err[0] != nil {
fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error())
}
if n > 1 {
for i := 1; i < n; i++ {
if err[i] != nil {
b.WriteString("\n")
fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error())
}
}
}
return b.String()
}
}
var _ StructValidator = &defaultValidator{}
// ValidateStruct receives any kind of type, but only performed struct or pointer to struct type.
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if obj == nil {
return nil
}
value := reflect.ValueOf(obj)
switch value.Kind() {
case reflect.Ptr:
return v.ValidateStruct(value.Elem().Interface())
case reflect.Struct:
return v.validateStruct(obj)
case reflect.Slice, reflect.Array:
count := value.Len()
validateRet := make(SliceValidationError, 0)
for i := 0; i < count; i++ {
if err := v.ValidateStruct(value.Index(i).Interface()); err != nil {
validateRet = append(validateRet, err)
}
}
if len(validateRet) == 0 {
return nil
}
return validateRet
default:
return nil
}
}
// validateStruct receives struct type
func (v *defaultValidator) validateStruct(obj interface{}) error {
v.lazyinit()
return v.validate.Struct(obj)
}
// Engine returns the underlying validator engine which powers the default
// Validator instance. This is useful if you want to register custom validations
// or struct level validations. See validator GoDoc for more info -
// https://pkg.go.dev/github.com/go-playground/validator/v10
func (v *defaultValidator) Engine() interface{} {
v.lazyinit()
return v.validate
}
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
v.validate.SetTagName("binding")
})
}

View File

@ -0,0 +1,62 @@
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"errors"
"net/http"
)
const defaultMemory = 32 << 20
type formBinding struct{}
type formPostBinding struct{}
type formMultipartBinding struct{}
func (formBinding) Name() string {
return "form"
}
func (formBinding) Bind(req *http.Request, obj interface{}) error {
if err := req.ParseForm(); err != nil {
return err
}
if err := req.ParseMultipartForm(defaultMemory); err != nil && !errors.Is(err, http.ErrNotMultipart) {
return err
}
if err := mapForm(obj, req.Form); err != nil {
return err
}
return validate(obj)
}
func (formPostBinding) Name() string {
return "form-urlencoded"
}
func (formPostBinding) Bind(req *http.Request, obj interface{}) error {
if err := req.ParseForm(); err != nil {
return err
}
if err := mapForm(obj, req.PostForm); err != nil {
return err
}
return validate(obj)
}
func (formMultipartBinding) Name() string {
return "multipart/form-data"
}
func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error {
if err := req.ParseMultipartForm(defaultMemory); err != nil {
return err
}
if err := mappingByPtr(obj, (*multipartRequest)(req), "form"); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,403 @@
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"time"
"go_dreamfactory/lego/utils/convert"
)
var (
errUnknownType = errors.New("unknown type")
// ErrConvertMapStringSlice can not covert to map[string][]string
ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings")
// ErrConvertToMapString can not convert to map[string]string
ErrConvertToMapString = errors.New("can not convert to map of strings")
)
func mapURI(ptr interface{}, m map[string][]string) error {
return mapFormByTag(ptr, m, "uri")
}
func mapForm(ptr interface{}, form map[string][]string) error {
return mapFormByTag(ptr, form, "form")
}
func MapFormWithTag(ptr interface{}, form map[string][]string, tag string) error {
return mapFormByTag(ptr, form, tag)
}
var emptyField = reflect.StructField{}
func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error {
// Check if ptr is a map
ptrVal := reflect.ValueOf(ptr)
var pointed interface{}
if ptrVal.Kind() == reflect.Ptr {
ptrVal = ptrVal.Elem()
pointed = ptrVal.Interface()
}
if ptrVal.Kind() == reflect.Map &&
ptrVal.Type().Key().Kind() == reflect.String {
if pointed != nil {
ptr = pointed
}
return setFormMap(ptr, form)
}
return mappingByPtr(ptr, formSource(form), tag)
}
// setter tries to set value on a walking by fields of a struct
type setter interface {
TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSet bool, err error)
}
type formSource map[string][]string
var _ setter = formSource(nil)
// TrySet tries to set a value by request's form source (like map[string][]string)
func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSet bool, err error) {
return setByForm(value, field, form, tagValue, opt)
}
func mappingByPtr(ptr interface{}, setter setter, tag string) error {
_, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag)
return err
}
func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
if field.Tag.Get(tag) == "-" { // just ignoring this field
return false, nil
}
vKind := value.Kind()
if vKind == reflect.Ptr {
var isNew bool
vPtr := value
if value.IsNil() {
isNew = true
vPtr = reflect.New(value.Type().Elem())
}
isSet, err := mapping(vPtr.Elem(), field, setter, tag)
if err != nil {
return false, err
}
if isNew && isSet {
value.Set(vPtr)
}
return isSet, nil
}
if vKind != reflect.Struct || !field.Anonymous {
ok, err := tryToSetValue(value, field, setter, tag)
if err != nil {
return false, err
}
if ok {
return true, nil
}
}
if vKind == reflect.Struct {
tValue := value.Type()
var isSet bool
for i := 0; i < value.NumField(); i++ {
sf := tValue.Field(i)
if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue
}
ok, err := mapping(value.Field(i), sf, setter, tag)
if err != nil {
return false, err
}
isSet = isSet || ok
}
return isSet, nil
}
return false, nil
}
type setOptions struct {
isDefaultExists bool
defaultValue string
}
func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
var tagValue string
var setOpt setOptions
tagValue = field.Tag.Get(tag)
tagValue, opts := head(tagValue, ",")
if tagValue == "" { // default value is FieldName
tagValue = field.Name
}
if tagValue == "" { // when field is "emptyField" variable
return false, nil
}
var opt string
for len(opts) > 0 {
opt, opts = head(opts, ",")
if k, v := head(opt, "="); k == "default" {
setOpt.isDefaultExists = true
setOpt.defaultValue = v
}
}
return setter.TrySet(value, field, tagValue, setOpt)
}
func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) {
vs, ok := form[tagValue]
if !ok && !opt.isDefaultExists {
return false, nil
}
switch value.Kind() {
case reflect.Slice:
if !ok {
vs = []string{opt.defaultValue}
}
return true, setSlice(vs, value, field)
case reflect.Array:
if !ok {
vs = []string{opt.defaultValue}
}
if len(vs) != value.Len() {
return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
}
return true, setArray(vs, value, field)
default:
var val string
if !ok {
val = opt.defaultValue
}
if len(vs) > 0 {
val = vs[0]
}
return true, setWithProperType(val, value, field)
}
}
func setWithProperType(val string, value reflect.Value, field reflect.StructField) error {
switch value.Kind() {
case reflect.Int:
return setIntField(val, 0, value)
case reflect.Int8:
return setIntField(val, 8, value)
case reflect.Int16:
return setIntField(val, 16, value)
case reflect.Int32:
return setIntField(val, 32, value)
case reflect.Int64:
switch value.Interface().(type) {
case time.Duration:
return setTimeDuration(val, value)
}
return setIntField(val, 64, value)
case reflect.Uint:
return setUintField(val, 0, value)
case reflect.Uint8:
return setUintField(val, 8, value)
case reflect.Uint16:
return setUintField(val, 16, value)
case reflect.Uint32:
return setUintField(val, 32, value)
case reflect.Uint64:
return setUintField(val, 64, value)
case reflect.Bool:
return setBoolField(val, value)
case reflect.Float32:
return setFloatField(val, 32, value)
case reflect.Float64:
return setFloatField(val, 64, value)
case reflect.String:
value.SetString(val)
case reflect.Struct:
switch value.Interface().(type) {
case time.Time:
return setTimeField(val, field, value)
}
return json.Unmarshal(convert.StringToBytes(val), value.Addr().Interface())
case reflect.Map:
return json.Unmarshal(convert.StringToBytes(val), value.Addr().Interface())
default:
return errUnknownType
}
return nil
}
func setIntField(val string, bitSize int, field reflect.Value) error {
if val == "" {
val = "0"
}
intVal, err := strconv.ParseInt(val, 10, bitSize)
if err == nil {
field.SetInt(intVal)
}
return err
}
func setUintField(val string, bitSize int, field reflect.Value) error {
if val == "" {
val = "0"
}
uintVal, err := strconv.ParseUint(val, 10, bitSize)
if err == nil {
field.SetUint(uintVal)
}
return err
}
func setBoolField(val string, field reflect.Value) error {
if val == "" {
val = "false"
}
boolVal, err := strconv.ParseBool(val)
if err == nil {
field.SetBool(boolVal)
}
return err
}
func setFloatField(val string, bitSize int, field reflect.Value) error {
if val == "" {
val = "0.0"
}
floatVal, err := strconv.ParseFloat(val, bitSize)
if err == nil {
field.SetFloat(floatVal)
}
return err
}
func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
timeFormat := structField.Tag.Get("time_format")
if timeFormat == "" {
timeFormat = time.RFC3339
}
switch tf := strings.ToLower(timeFormat); tf {
case "unix", "unixnano":
tv, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return err
}
d := time.Duration(1)
if tf == "unixnano" {
d = time.Second
}
t := time.Unix(tv/int64(d), tv%int64(d))
value.Set(reflect.ValueOf(t))
return nil
}
if val == "" {
value.Set(reflect.ValueOf(time.Time{}))
return nil
}
l := time.Local
if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
l = time.UTC
}
if locTag := structField.Tag.Get("time_location"); locTag != "" {
loc, err := time.LoadLocation(locTag)
if err != nil {
return err
}
l = loc
}
t, err := time.ParseInLocation(timeFormat, val, l)
if err != nil {
return err
}
value.Set(reflect.ValueOf(t))
return nil
}
func setArray(vals []string, value reflect.Value, field reflect.StructField) error {
for i, s := range vals {
err := setWithProperType(s, value.Index(i), field)
if err != nil {
return err
}
}
return nil
}
func setSlice(vals []string, value reflect.Value, field reflect.StructField) error {
slice := reflect.MakeSlice(value.Type(), len(vals), len(vals))
err := setArray(vals, slice, field)
if err != nil {
return err
}
value.Set(slice)
return nil
}
func setTimeDuration(val string, value reflect.Value) error {
d, err := time.ParseDuration(val)
if err != nil {
return err
}
value.Set(reflect.ValueOf(d))
return nil
}
func head(str, sep string) (head string, tail string) {
idx := strings.Index(str, sep)
if idx < 0 {
return str, ""
}
return str[:idx], str[idx+len(sep):]
}
func setFormMap(ptr interface{}, form map[string][]string) error {
el := reflect.TypeOf(ptr).Elem()
if el.Kind() == reflect.Slice {
ptrMap, ok := ptr.(map[string][]string)
if !ok {
return ErrConvertMapStringSlice
}
for k, v := range form {
ptrMap[k] = v
}
return nil
}
ptrMap, ok := ptr.(map[string]string)
if !ok {
return ErrConvertToMapString
}
for k, v := range form {
ptrMap[k] = v[len(v)-1] // pick last
}
return nil
}

View File

@ -0,0 +1,34 @@
package binding
import (
"net/http"
"net/textproto"
"reflect"
)
type headerBinding struct{}
func (headerBinding) Name() string {
return "header"
}
func (headerBinding) Bind(req *http.Request, obj interface{}) error {
if err := mapHeader(obj, req.Header); err != nil {
return err
}
return validate(obj)
}
func mapHeader(ptr interface{}, h map[string][]string) error {
return mappingByPtr(ptr, headerSource(h), "header")
}
type headerSource map[string][]string
var _ setter = headerSource(nil)
func (hs headerSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (bool, error) {
return setByForm(value, field, hs, textproto.CanonicalMIMEHeaderKey(tagValue), opt)
}

View File

@ -0,0 +1,55 @@
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
)
// EnableDecoderUseNumber is used to call the UseNumber method on the JSON
// Decoder instance. UseNumber causes the Decoder to unmarshal a number into an
// interface{} as a Number instead of as a float64.
var EnableDecoderUseNumber = false
// EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method
// on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to
// return an error when the destination is a struct and the input contains object
// keys which do not match any non-ignored, exported fields in the destination.
var EnableDecoderDisallowUnknownFields = false
type jsonBinding struct{}
func (jsonBinding) Name() string {
return "json"
}
func (jsonBinding) Bind(req *http.Request, obj interface{}) error {
if req == nil || req.Body == nil {
return errors.New("invalid request")
}
return decodeJSON(req.Body, obj)
}
func (jsonBinding) BindBody(body []byte, obj interface{}) error {
return decodeJSON(bytes.NewReader(body), obj)
}
func decodeJSON(r io.Reader, obj interface{}) error {
decoder := json.NewDecoder(r)
if EnableDecoderUseNumber {
decoder.UseNumber()
}
if EnableDecoderDisallowUnknownFields {
decoder.DisallowUnknownFields()
}
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,31 @@
package binding
import (
"bytes"
"io"
"net/http"
"github.com/ugorji/go/codec"
)
type msgpackBinding struct{}
func (msgpackBinding) Name() string {
return "msgpack"
}
func (msgpackBinding) Bind(req *http.Request, obj interface{}) error {
return decodeMsgPack(req.Body, obj)
}
func (msgpackBinding) BindBody(body []byte, obj interface{}) error {
return decodeMsgPack(bytes.NewReader(body), obj)
}
func decodeMsgPack(r io.Reader, obj interface{}) error {
cdc := new(codec.MsgpackHandle)
if err := codec.NewDecoder(r, cdc).Decode(&obj); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,74 @@
// Copyright 2019 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"errors"
"mime/multipart"
"net/http"
"reflect"
)
type multipartRequest http.Request
var _ setter = (*multipartRequest)(nil)
var (
// ErrMultiFileHeader multipart.FileHeader invalid
ErrMultiFileHeader = errors.New("unsupported field type for multipart.FileHeader")
// ErrMultiFileHeaderLenInvalid array for []*multipart.FileHeader len invalid
ErrMultiFileHeaderLenInvalid = errors.New("unsupported len of array for []*multipart.FileHeader")
)
// TrySet tries to set a value by the multipart request with the binding a form file
func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (bool, error) {
if files := r.MultipartForm.File[key]; len(files) != 0 {
return setByMultipartFormFile(value, field, files)
}
return setByForm(value, field, r.MultipartForm.Value, key, opt)
}
func setByMultipartFormFile(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSet bool, err error) {
switch value.Kind() {
case reflect.Ptr:
switch value.Interface().(type) {
case *multipart.FileHeader:
value.Set(reflect.ValueOf(files[0]))
return true, nil
}
case reflect.Struct:
switch value.Interface().(type) {
case multipart.FileHeader:
value.Set(reflect.ValueOf(*files[0]))
return true, nil
}
case reflect.Slice:
slice := reflect.MakeSlice(value.Type(), len(files), len(files))
isSet, err = setArrayOfMultipartFormFiles(slice, field, files)
if err != nil || !isSet {
return isSet, err
}
value.Set(slice)
return true, nil
case reflect.Array:
return setArrayOfMultipartFormFiles(value, field, files)
}
return false, ErrMultiFileHeader
}
func setArrayOfMultipartFormFiles(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSet bool, err error) {
if value.Len() != len(files) {
return false, ErrMultiFileHeaderLenInvalid
}
for i := range files {
set, err := setByMultipartFormFile(value.Index(i), field, files[i:i+1])
if err != nil || !set {
return set, err
}
}
return true, nil
}

View File

@ -0,0 +1,35 @@
package binding
import (
"errors"
"io/ioutil"
"net/http"
"google.golang.org/protobuf/proto"
)
type protobufBinding struct{}
func (protobufBinding) Name() string {
return "protobuf"
}
func (b protobufBinding) Bind(req *http.Request, obj interface{}) error {
buf, err := ioutil.ReadAll(req.Body)
if err != nil {
return err
}
return b.BindBody(buf, obj)
}
func (protobufBinding) BindBody(body []byte, obj interface{}) error {
msg, ok := obj.(proto.Message)
if !ok {
return errors.New("obj is not ProtoMessage")
}
if err := proto.Unmarshal(body, msg); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,17 @@
package binding
import "net/http"
type queryBinding struct{}
func (queryBinding) Name() string {
return "query"
}
func (queryBinding) Bind(req *http.Request, obj interface{}) error {
values := req.URL.Query()
if err := mapForm(obj, values); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,14 @@
package binding
type uriBinding struct{}
func (uriBinding) Name() string {
return "uri"
}
func (uriBinding) BindUri(m map[string][]string, obj interface{}) error {
if err := mapURI(obj, m); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,33 @@
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package binding
import (
"bytes"
"encoding/xml"
"io"
"net/http"
)
type xmlBinding struct{}
func (xmlBinding) Name() string {
return "xml"
}
func (xmlBinding) Bind(req *http.Request, obj interface{}) error {
return decodeXML(req.Body, obj)
}
func (xmlBinding) BindBody(body []byte, obj interface{}) error {
return decodeXML(bytes.NewReader(body), obj)
}
func decodeXML(r io.Reader, obj interface{}) error {
decoder := xml.NewDecoder(r)
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}

View File

@ -0,0 +1,31 @@
package binding
import (
"bytes"
"io"
"net/http"
"gopkg.in/yaml.v2"
)
type yamlBinding struct{}
func (yamlBinding) Name() string {
return "yaml"
}
func (yamlBinding) Bind(req *http.Request, obj interface{}) error {
return decodeYAML(req.Body, obj)
}
func (yamlBinding) BindBody(body []byte, obj interface{}) error {
return decodeYAML(bytes.NewReader(body), obj)
}
func decodeYAML(r io.Reader, obj interface{}) error {
decoder := yaml.NewDecoder(r)
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}

73
lego/sys/gin/core.go Normal file
View File

@ -0,0 +1,73 @@
package gin
import (
"net/http"
"go_dreamfactory/lego/sys/gin/engine"
)
type ISys interface {
engine.IRoutes
Close() (err error)
}
var defsys ISys
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func Close() (err error) {
return defsys.Close()
}
func Use(handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.Use(handlers...)
}
func Handle(httpMethod string, relativePath string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.Handle(httpMethod, relativePath, handlers...)
}
func Any(relativePath string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.Any(relativePath, handlers...)
}
func GET(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.GET(httpMethod, handlers...)
}
func POST(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.POST(httpMethod, handlers...)
}
func DELETE(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.DELETE(httpMethod, handlers...)
}
func PATCH(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.PATCH(httpMethod, handlers...)
}
func PUT(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.PUT(httpMethod, handlers...)
}
func OPTIONS(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.OPTIONS(httpMethod, handlers...)
}
func HEAD(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.HEAD(httpMethod, handlers...)
}
func StaticFile(relativePath string, filepath string) engine.IRoutes {
return defsys.StaticFile(relativePath, filepath)
}
func StaticFileFS(relativePath string, filepath string, fs http.FileSystem) engine.IRoutes {
return defsys.StaticFileFS(relativePath, filepath, fs)
}
func Static(relativePath string, root string) engine.IRoutes {
return defsys.Static(relativePath, root)
}
func StaticFS(relativePath string, fs http.FileSystem) engine.IRoutes {
return defsys.StaticFS(relativePath, fs)
}

View File

@ -0,0 +1,858 @@
package engine
import (
"errors"
"io"
"io/ioutil"
"math"
"mime/multipart"
"net"
"net/http"
"net/url"
"os"
"strings"
"sync"
"time"
"go_dreamfactory/lego/sys/gin/binding"
"go_dreamfactory/lego/sys/gin/render"
)
const (
MIMEJSON = binding.MIMEJSON
MIMEHTML = binding.MIMEHTML
MIMEXML = binding.MIMEXML
MIMEXML2 = binding.MIMEXML2
MIMEPlain = binding.MIMEPlain
MIMEPOSTForm = binding.MIMEPOSTForm
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
MIMEYAML = binding.MIMEYAML
)
const abortIndex int8 = math.MaxInt8 >> 1
func newContext(sys ISys, engine *Engine, params *Params, skippedNodes *[]skippedNode) *Context {
return &Context{
engine: engine,
params: params,
skippedNodes: skippedNodes,
writermem: ResponseWriter{log: sys},
}
}
type Context struct {
Sys ISys
engine *Engine
writermem ResponseWriter
Request *http.Request
Writer IResponseWriter
Params Params
handlers HandlersChain
index int8
fullPath string
params *Params
skippedNodes *[]skippedNode
mu sync.RWMutex
Keys map[string]interface{}
Errors errorMsgs
Accepted []string
queryCache url.Values
formCache url.Values
sameSite http.SameSite
}
func (this *Context) Copy() *Context {
cp := Context{
writermem: this.writermem,
Request: this.Request,
Params: this.Params,
engine: this.engine,
}
cp.writermem.ResponseWriter = nil
cp.Writer = &cp.writermem
cp.index = abortIndex
cp.handlers = nil
cp.Keys = map[string]interface{}{}
for k, v := range this.Keys {
cp.Keys[k] = v
}
paramCopy := make([]Param, len(cp.Params))
copy(paramCopy, cp.Params)
cp.Params = paramCopy
return &cp
}
func (this *Context) HandlerName() string {
return nameOfFunction(this.handlers.Last())
}
func (this *Context) HandlerNames() []string {
hn := make([]string, 0, len(this.handlers))
for _, val := range this.handlers {
hn = append(hn, nameOfFunction(val))
}
return hn
}
func (this *Context) Handler() HandlerFunc {
return this.handlers.Last()
}
/*
FullPath 返回匹配的路由完整路径 对于未找到的路线
返回一个空字符串
*/
func (c *Context) FullPath() string {
return c.fullPath
}
func (this *Context) Next() {
this.index++
for this.index < int8(len(this.handlers)) {
this.handlers[this.index](this)
this.index++
}
}
/*
如果当前上下文被中止IsAborted 返回 true
*/
func (this *Context) IsAborted() bool {
return this.index >= abortIndex
}
/*
Abort 防止挂起的处理程序被调用 请注意这不会停止当前处理程序
假设你有一个授权中间件来验证当前请求是否被授权
如果授权失败例如密码不匹配调用 Abort 以确保剩余的 handlers
因为这个请求没有被调用
*/
func (this *Context) Abort() {
this.index = abortIndex
}
/*
AbortWithStatus 调用 `Abort()` 并使用指定的状态代码写入标头
例如验证请求失败的尝试可以使用context.AbortWithStatus(401)
*/
func (this *Context) AbortWithStatus(code int) {
this.Status(code)
this.Writer.WriteHeaderNow()
this.Abort()
}
func (this *Context) AbortWithStatusJSON(code int, jsonObj interface{}) {
this.Abort()
this.JSON(code, jsonObj)
}
func (this *Context) AbortWithError(code int, err error) *Error {
this.AbortWithStatus(code)
return this.Error(err)
}
func (this *Context) Set(key string, value interface{}) {
this.mu.Lock()
if this.Keys == nil {
this.Keys = make(map[string]interface{})
}
this.Keys[key] = value
this.mu.Unlock()
}
func (this *Context) Get(key string) (value interface{}, exists bool) {
this.mu.RLock()
value, exists = this.Keys[key]
this.mu.RUnlock()
return
}
/*
如果存在MustGet 返回给定键的值否则抛出异常
*/
func (this *Context) MustGet(key string) interface{} {
if value, exists := this.Get(key); exists {
return value
}
panic("Key \"" + key + "\" does not exist")
}
func (this *Context) GetString(key string) (s string) {
if val, ok := this.Get(key); ok && val != nil {
s, _ = val.(string)
}
return
}
func (this *Context) GetBool(key string) (b bool) {
if val, ok := this.Get(key); ok && val != nil {
b, _ = val.(bool)
}
return
}
func (this *Context) GetInt(key string) (i int) {
if val, ok := this.Get(key); ok && val != nil {
i, _ = val.(int)
}
return
}
func (this *Context) GetInt64(key string) (i64 int64) {
if val, ok := this.Get(key); ok && val != nil {
i64, _ = val.(int64)
}
return
}
func (this *Context) GetUint(key string) (ui uint) {
if val, ok := this.Get(key); ok && val != nil {
ui, _ = val.(uint)
}
return
}
func (c *Context) GetUInt32(key string) (i uint32) {
if val, ok := c.Get(key); ok && val != nil {
i, _ = val.(uint32)
}
return
}
func (this *Context) GetUint64(key string) (ui64 uint64) {
if val, ok := this.Get(key); ok && val != nil {
ui64, _ = val.(uint64)
}
return
}
func (this *Context) GetFloat64(key string) (f64 float64) {
if val, ok := this.Get(key); ok && val != nil {
f64, _ = val.(float64)
}
return
}
func (this *Context) GetTime(key string) (t time.Time) {
if val, ok := this.Get(key); ok && val != nil {
t, _ = val.(time.Time)
}
return
}
func (this *Context) GetDuration(key string) (d time.Duration) {
if val, ok := this.Get(key); ok && val != nil {
d, _ = val.(time.Duration)
}
return
}
func (this *Context) GetStringSlice(key string) (ss []string) {
if val, ok := this.Get(key); ok && val != nil {
ss, _ = val.([]string)
}
return
}
func (this *Context) GetStringMap(key string) (sm map[string]interface{}) {
if val, ok := this.Get(key); ok && val != nil {
sm, _ = val.(map[string]interface{})
}
return
}
func (this *Context) GetStringMapString(key string) (sms map[string]string) {
if val, ok := this.Get(key); ok && val != nil {
sms, _ = val.(map[string]string)
}
return
}
func (this *Context) GetStringMapStringSlice(key string) (smss map[string][]string) {
if val, ok := this.Get(key); ok && val != nil {
smss, _ = val.(map[string][]string)
}
return
}
func (this *Context) Header(key, value string) {
if value == "" {
this.Writer.Header().Del(key)
return
}
this.Writer.Header().Set(key, value)
}
// Status sets the HTTP response code.
func (this *Context) Status(code int) {
this.Writer.WriteHeader(code)
}
func (this *Context) Param(key string) string {
return this.Params.ByName(key)
}
func (this *Context) AddParam(key, value string) {
this.Params = append(this.Params, Param{Key: key, Value: value})
}
func (this *Context) Query(key string) (value string) {
value, _ = this.GetQuery(key)
return
}
func (this *Context) DefaultQuery(key, defaultValue string) string {
if value, ok := this.GetQuery(key); ok {
return value
}
return defaultValue
}
func (this *Context) GetQuery(key string) (string, bool) {
if values, ok := this.GetQueryArray(key); ok {
return values[0], ok
}
return "", false
}
func (this *Context) initQueryCache() {
if this.queryCache == nil {
if this.Request != nil {
this.queryCache = this.Request.URL.Query()
} else {
this.queryCache = url.Values{}
}
}
}
func (this *Context) GetQueryArray(key string) (values []string, ok bool) {
this.initQueryCache()
values, ok = this.queryCache[key]
return
}
func (this *Context) QueryMap(key string) (dicts map[string]string) {
dicts, _ = this.GetQueryMap(key)
return
}
func (this *Context) GetQueryMap(key string) (map[string]string, bool) {
this.initQueryCache()
return this.get(this.queryCache, key)
}
func (this *Context) PostForm(key string) (value string) {
value, _ = this.GetPostForm(key)
return
}
func (this *Context) GetPostForm(key string) (string, bool) {
if values, ok := this.GetPostFormArray(key); ok {
return values[0], ok
}
return "", false
}
func (this *Context) initFormCache() {
if this.formCache == nil {
this.formCache = make(url.Values)
req := this.Request
if err := req.ParseMultipartForm(this.engine.MaxMultipartMemory); err != nil {
if !errors.Is(err, http.ErrNotMultipart) {
this.Sys.Errorf("error on parse multipart form array: %v", err)
}
}
this.formCache = req.PostForm
}
}
func (this *Context) GetPostFormArray(key string) (values []string, ok bool) {
this.initFormCache()
values, ok = this.formCache[key]
return
}
func (this *Context) PostFormMap(key string) (dicts map[string]string) {
dicts, _ = this.GetPostFormMap(key)
return
}
func (this *Context) GetPostFormMap(key string) (map[string]string, bool) {
this.initFormCache()
return this.get(this.formCache, key)
}
func (this *Context) FormFile(name string) (*multipart.FileHeader, error) {
if this.Request.MultipartForm == nil {
if err := this.Request.ParseMultipartForm(this.engine.MaxMultipartMemory); err != nil {
return nil, err
}
}
f, fh, err := this.Request.FormFile(name)
if err != nil {
return nil, err
}
f.Close()
return fh, err
}
/*
MultipartForm 是解析后的多部分表单包括文件上传
*/
func (this *Context) MultipartForm() (*multipart.Form, error) {
err := this.Request.ParseMultipartForm(this.engine.MaxMultipartMemory)
return this.Request.MultipartForm, err
}
/*
保存上传文件
*/
func (this *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, src)
return err
}
func (this *Context) GetRawData() ([]byte, error) {
return ioutil.ReadAll(this.Request.Body)
}
//序列化--------------------------------------------------------------------------------------------
func (this *Context) Bind(obj interface{}) error {
b := binding.Default(this.Request.Method, this.ContentType())
return this.MustBindWith(obj, b)
}
func (this *Context) ShouldBindJSON(obj interface{}) error {
return this.ShouldBindWith(obj, binding.JSON)
}
func (this *Context) MustBindWith(obj interface{}, b binding.Binding) error {
if err := this.ShouldBindWith(obj, b); err != nil {
this.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
return err
}
return nil
}
func (this *Context) ShouldBindWith(obj interface{}, b binding.Binding) error {
return b.Bind(this.Request, obj)
}
func (this *Context) ShouldBindUri(obj interface{}) error {
m := make(map[string][]string)
for _, v := range this.Params {
m[v.Key] = []string{v.Value}
}
return binding.Uri.BindUri(m, obj)
}
func (this *Context) BindJSON(obj interface{}) error {
return this.MustBindWith(obj, binding.JSON)
}
func (this *Context) BindXML(obj interface{}) error {
return this.MustBindWith(obj, binding.XML)
}
func (this *Context) BindQuery(obj interface{}) error {
return this.MustBindWith(obj, binding.Query)
}
func (this *Context) BindYAML(obj interface{}) error {
return this.MustBindWith(obj, binding.YAML)
}
func (this *Context) BindHeader(obj interface{}) error {
return this.MustBindWith(obj, binding.Header)
}
func (this *Context) BindUri(obj interface{}) error {
if err := this.ShouldBindUri(obj); err != nil {
this.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
return err
}
return nil
}
//输出-----------------------------------------------------------------------------------------
func (this *Context) HTML(code int, name string, obj interface{}) {
instance := this.engine.HTMLRender.Instance(name, obj)
this.Render(code, instance)
}
func (this *Context) IndentedJSON(code int, obj interface{}) {
this.Render(code, render.IndentedJSON{Data: obj})
}
func (this *Context) SecureJSON(code int, obj interface{}) {
this.Render(code, render.SecureJSON{Prefix: this.engine.secureJSONPrefix, Data: obj})
}
func (this *Context) JSONP(code int, obj interface{}) {
callback := this.DefaultQuery("callback", "")
if callback == "" {
this.Render(code, render.JSON{Data: obj})
return
}
this.Render(code, render.JsonpJSON{Callback: callback, Data: obj})
}
func (this *Context) JSON(code int, obj interface{}) {
this.Render(code, render.JSON{Data: obj})
}
func (this *Context) AsciiJSON(code int, obj interface{}) {
this.Render(code, render.AsciiJSON{Data: obj})
}
func (this *Context) PureJSON(code int, obj interface{}) {
this.Render(code, render.PureJSON{Data: obj})
}
func (this *Context) XML(code int, obj interface{}) {
this.Render(code, render.XML{Data: obj})
}
func (this *Context) YAML(code int, obj interface{}) {
this.Render(code, render.YAML{Data: obj})
}
func (this *Context) ProtoBuf(code int, obj interface{}) {
this.Render(code, render.ProtoBuf{Data: obj})
}
func (this *Context) String(code int, format string, values ...interface{}) {
this.Render(code, render.String{Format: format, Data: values})
}
func (this *Context) Redirect(code int, location string) {
this.Render(-1, render.Redirect{
Code: code,
Location: location,
Request: this.Request,
})
}
func (this *Context) Data(code int, contentType string, data []byte) {
this.Render(code, render.Data{
ContentType: contentType,
Data: data,
})
}
func (this *Context) DataFromReader(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string) {
this.Render(code, render.Reader{
Headers: extraHeaders,
ContentType: contentType,
ContentLength: contentLength,
Reader: reader,
})
}
func (this *Context) File(filepath string) {
http.ServeFile(this.Writer, this.Request, filepath)
}
/*渲染页面接口*/
func (this *Context) Render(code int, r render.Render) {
this.Status(code)
if !bodyAllowedForStatus(code) {
r.WriteContentType(this.Writer)
this.Writer.WriteHeaderNow()
return
}
if err := r.Render(this.Writer); err != nil {
panic(err)
}
}
func (this *Context) FileFromFS(filepath string, fs http.FileSystem) {
defer func(old string) {
this.Request.URL.Path = old
}(this.Request.URL.Path)
this.Request.URL.Path = filepath
http.FileServer(fs).ServeHTTP(this.Writer, this.Request)
}
/*
以高效的方式将指定的文件写入正文流
在客户端通常会使用给定的文件名下载文件
*/
func (this *Context) FileAttachment(filepath, filename string) {
if isASCII(filename) {
this.Writer.Header().Set("Content-Disposition", `attachment; filename="`+filename+`"`)
} else {
this.Writer.Header().Set("Content-Disposition", `attachment; filename*=UTF-8''`+url.QueryEscape(filename))
}
http.ServeFile(this.Writer, this.Request, filepath)
}
func (this *Context) Stream(step func(w io.Writer) bool) bool {
w := this.Writer
clientGone := w.CloseNotify()
for {
select {
case <-clientGone:
return true
default:
keepOpen := step(w)
w.Flush()
if !keepOpen {
return false
}
}
}
}
type Negotiate struct {
Offered []string
HTMLName string
HTMLData interface{}
JSONData interface{}
XMLData interface{}
YAMLData interface{}
Data interface{}
}
func (this *Context) Negotiate(code int, config Negotiate) {
switch this.NegotiateFormat(config.Offered...) {
case binding.MIMEJSON:
data := chooseData(config.JSONData, config.Data)
this.JSON(code, data)
case binding.MIMEHTML:
data := chooseData(config.HTMLData, config.Data)
this.HTML(code, config.HTMLName, data)
case binding.MIMEXML:
data := chooseData(config.XMLData, config.Data)
this.XML(code, data)
case binding.MIMEYAML:
data := chooseData(config.YAMLData, config.Data)
this.YAML(code, data)
default:
this.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) // nolint: errcheck
}
}
func (this *Context) NegotiateFormat(offered ...string) string {
assert1(len(offered) > 0, "you must provide at least one offer")
if this.Accepted == nil {
this.Accepted = parseAccept(this.requestHeader("Accept"))
}
if len(this.Accepted) == 0 {
return offered[0]
}
for _, accepted := range this.Accepted {
for _, offer := range offered {
// According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers,
// therefore we can just iterate over the string without casting it into []rune
i := 0
for ; i < len(accepted); i++ {
if accepted[i] == '*' || offer[i] == '*' {
return offer
}
if accepted[i] != offer[i] {
break
}
}
if i == len(accepted) {
return offer
}
}
}
return ""
}
func (this *Context) SetAccepted(formats ...string) {
this.Accepted = formats
}
func (this *Context) Deadline() (deadline time.Time, ok bool) {
if this.Request == nil || this.Request.Context() == nil {
return
}
return this.Request.Context().Deadline()
}
func (this *Context) Done() <-chan struct{} {
if this.Request == nil || this.Request.Context() == nil {
return nil
}
return this.Request.Context().Done()
}
func (this *Context) Err() error {
if this.Request == nil || this.Request.Context() == nil {
return nil
}
return this.Request.Context().Err()
}
func (c *Context) Value(key interface{}) interface{} {
if key == 0 {
return c.Request
}
if keyAsString, ok := key.(string); ok {
if val, exists := c.Get(keyAsString); exists {
return val
}
}
if c.Request == nil || c.Request.Context() == nil {
return nil
}
return c.Request.Context().Value(key)
}
func (this *Context) ContentType() string {
return filterFlags(this.requestHeader("Content-Type"))
}
func (this *Context) RemoteIP() string {
ip, _, err := net.SplitHostPort(strings.TrimSpace(this.Request.RemoteAddr))
if err != nil {
return ""
}
return ip
}
func (this *Context) ClientIP() string {
// 检查我们是否在受信任的平台上运行,如果出错则继续向后运行
if this.engine.TrustedPlatform != "" {
// Developers can define their own header of Trusted Platform or use predefined constants
if addr := this.requestHeader(this.engine.TrustedPlatform); addr != "" {
return addr
}
}
/*
// 它还检查 remoteIP 是否是受信任的代理。
// 为了执行此验证,它将查看 IP 是否包含在至少一个 CIDR 块中
// 由 Engine.SetTrustedProxies() 定义
*/
remoteIP := net.ParseIP(this.RemoteIP())
if remoteIP == nil {
return ""
}
trusted := this.engine.isTrustedProxy(remoteIP)
if trusted && this.engine.ForwardedByClientIP && this.engine.RemoteIPHeaders != nil {
for _, headerName := range this.engine.RemoteIPHeaders {
ip, valid := this.engine.validateHeader(this.requestHeader(headerName))
if valid {
return ip
}
}
}
return remoteIP.String()
}
func (this *Context) IsWebsocket() bool {
if strings.Contains(strings.ToLower(this.requestHeader("Connection")), "upgrade") &&
strings.EqualFold(this.requestHeader("Upgrade"), "websocket") {
return true
}
return false
}
func (this *Context) SetSameSite(samesite http.SameSite) {
this.sameSite = samesite
}
func (this *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {
if path == "" {
path = "/"
}
http.SetCookie(this.Writer, &http.Cookie{
Name: name,
Value: url.QueryEscape(value),
MaxAge: maxAge,
Path: path,
Domain: domain,
SameSite: this.sameSite,
Secure: secure,
HttpOnly: httpOnly,
})
}
func (this *Context) Cookie(name string) (string, error) {
cookie, err := this.Request.Cookie(name)
if err != nil {
return "", err
}
val, _ := url.QueryUnescape(cookie.Value)
return val, nil
}
func (this *Context) Error(err error) *Error {
if err == nil {
panic("err is nil")
}
var parsedError *Error
ok := errors.As(err, &parsedError)
if !ok {
parsedError = &Error{
Err: err,
Type: ErrorTypePrivate,
}
}
this.Errors = append(this.Errors, parsedError)
return parsedError
}
func (this *Context) get(m map[string][]string, key string) (map[string]string, bool) {
dicts := make(map[string]string)
exist := false
for k, v := range m {
if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
exist = true
dicts[k[i+1:][:j]] = v[0]
}
}
}
return dicts, exist
}
func (this *Context) requestHeader(key string) string {
return this.Request.Header.Get(key)
}
func (this *Context) reset() {
this.Writer = &this.writermem
this.Params = this.Params[:0]
this.handlers = nil
this.index = -1
this.fullPath = ""
this.Keys = nil
this.Errors = this.Errors[:0]
this.Accepted = nil
this.queryCache = nil
this.formCache = nil
this.sameSite = 0
*this.params = (*this.params)[:0]
*this.skippedNodes = (*this.skippedNodes)[:0]
}
/*
bodyAllowedForStatus http.bodyAllowedForStatus 非导出函数的副本
*/
func bodyAllowedForStatus(status int) bool {
switch {
case status >= 100 && status <= 199:
return false
case status == http.StatusNoContent:
return false
case status == http.StatusNotModified:
return false
}
return true
}

View File

@ -0,0 +1,49 @@
package engine
import (
"net/http"
"go_dreamfactory/lego/sys/log"
)
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
func (c HandlersChain) Last() HandlerFunc {
if length := len(c); length > 0 {
return c[length-1]
}
return nil
}
type RouteInfo struct {
Method string
Path string
Handler string
HandlerFunc HandlerFunc
}
type RoutesInfo []RouteInfo
type ISys interface {
log.Ilogf
Debug() bool
}
type IRoutes interface {
Group(relativePath string, handlers ...HandlerFunc) IRoutes
Use(...HandlerFunc) IRoutes
Handle(string, string, ...HandlerFunc) IRoutes
Any(string, ...HandlerFunc) IRoutes
GET(string, ...HandlerFunc) IRoutes
POST(string, ...HandlerFunc) IRoutes
DELETE(string, ...HandlerFunc) IRoutes
PATCH(string, ...HandlerFunc) IRoutes
PUT(string, ...HandlerFunc) IRoutes
OPTIONS(string, ...HandlerFunc) IRoutes
HEAD(string, ...HandlerFunc) IRoutes
StaticFile(string, string) IRoutes
StaticFileFS(string, string, http.FileSystem) IRoutes
Static(string, string) IRoutes
StaticFS(string, http.FileSystem) IRoutes
}

View File

@ -0,0 +1,511 @@
package engine
import (
"html/template"
"net"
"net/http"
"path"
"strings"
"sync"
"go_dreamfactory/lego/sys/gin/render"
"go_dreamfactory/lego/utils/convert"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
/*
默认文件上传的最大尺寸
*/
const defaultMultipartMemory = 32 << 20 // 32 MB
/*
默认可信代理
*/
var defaultTrustedCIDRs = []*net.IPNet{
{ // 0.0.0.0/0 (IPv4)
IP: net.IP{0x0, 0x0, 0x0, 0x0},
Mask: net.IPMask{0x0, 0x0, 0x0, 0x0},
},
{ // ::/0 (IPv6)
IP: net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
Mask: net.IPMask{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
},
}
func NewEngine(sys ISys) (engine *Engine) {
engine = &Engine{
RouterGroup: RouterGroup{
Handlers: nil,
basePath: "/",
root: true,
},
sys: sys,
FuncMap: template.FuncMap{},
RedirectTrailingSlash: true,
RedirectFixedPath: false,
HandleMethodNotAllowed: false,
ForwardedByClientIP: true,
RemoteIPHeaders: []string{"X-Forwarded-For", "X-Real-IP"},
UseRawPath: false,
RemoveExtraSlash: false,
UnescapePathValues: true,
MaxMultipartMemory: defaultMultipartMemory,
trees: make(methodTrees, 0, 9),
delims: render.Delims{Left: "{{", Right: "}}"},
secureJSONPrefix: "while(1);",
trustedProxies: []string{"0.0.0.0/0"},
trustedCIDRs: defaultTrustedCIDRs,
}
engine.RouterGroup.engine = engine
engine.pool.New = func() interface{} {
return engine.allocateContext()
}
return
}
var (
default404Body = []byte("404 page not found")
default405Body = []byte("405 method not allowed")
)
var mimePlain = []string{MIMEPlain}
type Engine struct {
RouterGroup
sys ISys
UseRawPath bool
/*
如果启用路由器尝试修复当前请求路径如果没有
如果没有
已为其注册句柄
第一个多余的路径元素 ../ // 被删除。
之后路由器对清理后的路径进行不区分大小写的查找
如果可以找到该路由的句柄则路由器进行重定向
到正确的路径GET 请求的状态码为 301 GET 请求的状态码为 307
所有其他请求方法
例如 /FOO /..//Foo 可以重定向到 /foo。
RedirectTrailingSlash 与此选项无关
*/
RedirectFixedPath bool
/*
如果为真路径值将不转义
*/
UnescapePathValues bool
/*
如果当前路由无法匹配但启用自动重定向
带有不带尾部斜杠的路径的处理程序存在
例如如果 /foo/ 被请求但路由只存在于 /foo
对于 GET 请求客户端被重定向到 /foohttp 状态码为 301
对于所有其他请求方法则为 307
*/
RedirectTrailingSlash bool //
/*
如果启用路由器检查是否允许其他方法
当前路由如果当前请求无法路由
如果是这种情况则使用不允许的方法回答请求
HTTP 状态码 405
如果不允许其他方法则将请求委托给 NotFound
处理程序
*/
HandleMethodNotAllowed bool
/*
可以从 URL 中解析出一个参数即使带有额外的斜杠
*/
RemoveExtraSlash bool
/*
TrustedPlatform 如果设置为值 gin.Platform* 的常量则信任由设置的标头
那个平台比如判断客户端IP
*/
TrustedPlatform string
/*
ForwardedByClientIP 如果启用客户端 IP 将从请求的标头中解析
匹配存储在 `(*gin.Engine).RemoteIPHeaders` 中的那些 如果没有 IP
fetched, 它回退到从获取的 IP
`(*gin.Context).Request.RemoteAddr`
ForwardedByClientIP 布尔值
*/
ForwardedByClientIP bool
/*
RemoteIPHeaders 用于获取客户端 IP 时的 headers 列表
`(*gin.Engine).ForwardedByClientIP` `true` 并且
`(*gin.Context).Request.RemoteAddr` 被至少一个匹配
`(*gin.Engine).SetTrustedProxies()` 定义的列表的网络来源
*/
RemoteIPHeaders []string
/*
文件上传的最大尺寸
*/
MaxMultipartMemory int64
/*
是否使用H2C
*/
UseH2C bool
delims render.Delims
secureJSONPrefix string
HTMLRender render.HTMLRender
FuncMap template.FuncMap
noRoute HandlersChain
noMethod HandlersChain
allNoRoute HandlersChain
allNoMethod HandlersChain
pool sync.Pool
trees methodTrees
maxParams uint16
maxSections uint16
trustedProxies []string
trustedCIDRs []*net.IPNet
}
func (this *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := this.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()
this.handleHTTPRequest(c)
this.pool.Put(c)
}
func (this *Engine) Handler() http.Handler {
if !this.UseH2C {
return this
}
h2s := &http2.Server{}
return h2c.NewHandler(this, h2s)
}
/*
使用中间件
*/
func (this *Engine) Use(middleware ...HandlerFunc) IRoutes {
this.RouterGroup.Use(middleware...)
this.rebuild404Handlers()
this.rebuild405Handlers()
return this
}
/*
LoadHTMLGlob 加载由 glob 模式标识的 HTML 文件
并将结果与 HTML 渲染器相关联
*/
func (this *Engine) LoadHTMLGlob(pattern string) {
left := this.delims.Left
right := this.delims.Right
templ := template.Must(template.New("").Delims(left, right).Funcs(this.FuncMap).ParseGlob(pattern))
if this.sys.Debug() {
this.debugPrintLoadTemplate(templ)
this.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: this.FuncMap, Delims: this.delims}
return
}
this.SetHTMLTemplate(templ)
}
/*
LoadHTMLFiles 加载一段 HTML 文件
并将结果与 HTML 渲染器相关联
*/
func (this *Engine) LoadHTMLFiles(files ...string) {
if this.sys.Debug() {
this.HTMLRender = render.HTMLDebug{Files: files, FuncMap: this.FuncMap, Delims: this.delims}
return
}
templ := template.Must(template.New("").Delims(this.delims.Left, this.delims.Right).Funcs(this.FuncMap).ParseFiles(files...))
this.SetHTMLTemplate(templ)
}
func (this *Engine) SetHTMLTemplate(templ *template.Template) {
if len(this.trees) > 0 {
this.sys.Warnf(`Since SetHTMLTemplate() is NOT thread-safe. It should only be called
at initialization. ie. before any route is registered or the router is listening in a socket:
router := gin.Default()
router.SetHTMLTemplate(template) // << good place
`)
}
this.HTMLRender = render.HTMLProduction{Template: templ.Funcs(this.FuncMap)}
}
/*
设置template FuncMap
*/
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
engine.FuncMap = funcMap
}
/*
404 处理路由
*/
func (this *Engine) NoRoute(handlers ...HandlerFunc) {
this.noRoute = handlers
this.rebuild404Handlers()
}
/*
没有找到对应的方法
*/
func (this *Engine) NoMethod(handlers ...HandlerFunc) {
this.noMethod = handlers
this.rebuild405Handlers()
}
func (engine *Engine) Routes() (routes RoutesInfo) {
for _, tree := range engine.trees {
routes = iterate("", tree.method, routes, tree.root)
}
return routes
}
/*
设置信任代理
*/
func (this *Engine) SetTrustedProxies(trustedProxies []string) error {
this.trustedProxies = trustedProxies
return this.parseTrustedProxies()
}
func (this *Engine) addRoute(method, path string, handlers HandlersChain) {
assert1(path[0] == '/', "path must begin with '/'")
assert1(method != "", "HTTP method can not be empty")
assert1(len(handlers) > 0, "there must be at least one handler")
if this.sys.Debug() {
nuHandlers := len(handlers)
handlerName := nameOfFunction(handlers.Last())
this.sys.Debugf("%s:%s --> %s handlers:%d", method, path, handlerName, nuHandlers)
}
root := this.trees.get(method)
if root == nil {
root = new(node)
root.fullPath = "/"
this.trees = append(this.trees, methodTree{method: method, root: root})
}
root.addRoute(path, handlers)
// Update maxParams
if paramsCount := countParams(path); paramsCount > this.maxParams {
this.maxParams = paramsCount
}
if sectionsCount := countSections(path); sectionsCount > this.maxSections {
this.maxSections = sectionsCount
}
}
func (this *Engine) handleHTTPRequest(c *Context) {
httpMethod := c.Request.Method
rPath := c.Request.URL.Path
unescape := false
if this.UseRawPath && len(c.Request.URL.RawPath) > 0 {
rPath = c.Request.URL.RawPath
unescape = this.UnescapePathValues
}
if this.RemoveExtraSlash {
rPath = cleanPath(rPath)
}
t := this.trees
for i, tl := 0, len(t); i < tl; i++ {
if t[i].method != httpMethod {
continue
}
root := t[i].root
// Find route in tree
value := root.getValue(rPath, c.params, c.skippedNodes, unescape)
if value.params != nil {
c.Params = *value.params
}
if value.handlers != nil {
c.handlers = value.handlers
c.fullPath = value.fullPath
c.Next()
c.writermem.WriteHeaderNow()
return
}
if httpMethod != http.MethodConnect && rPath != "/" {
if value.tsr && this.RedirectTrailingSlash {
this.redirectTrailingSlash(c)
return
}
if this.RedirectFixedPath && this.redirectFixedPath(c, root, this.RedirectFixedPath) {
return
}
}
break
}
if this.HandleMethodNotAllowed {
for _, tree := range this.trees {
if tree.method == httpMethod {
continue
}
if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil {
c.handlers = this.allNoMethod
this.serveError(c, http.StatusMethodNotAllowed, default405Body)
return
}
}
}
c.handlers = this.allNoRoute
this.serveError(c, http.StatusNotFound, default404Body)
}
func (this *Engine) rebuild404Handlers() {
this.allNoRoute = this.combineHandlers(this.noRoute)
}
func (this *Engine) rebuild405Handlers() {
this.allNoMethod = this.combineHandlers(this.noMethod)
}
func (this *Engine) IsUnsafeTrustedProxies() bool {
return this.isTrustedProxy(net.ParseIP("0.0.0.0")) || this.isTrustedProxy(net.ParseIP("::"))
}
//validateHeader 将解析 X-Forwarded-For 标头并返回受信任的客户端 IP 地址
func (this *Engine) validateHeader(header string) (clientIP string, valid bool) {
if header == "" {
return "", false
}
items := strings.Split(header, ",")
for i := len(items) - 1; i >= 0; i-- {
ipStr := strings.TrimSpace(items[i])
ip := net.ParseIP(ipStr)
if ip == nil {
break
}
// X-Forwarded-For is appended by proxy
// Check IPs in reverse order and stop when find untrusted proxy
if (i == 0) || (!this.isTrustedProxy(ip)) {
return ipStr, true
}
}
return "", false
}
///目标Ip是否是可信
func (this *Engine) isTrustedProxy(ip net.IP) bool {
if this.trustedCIDRs == nil {
return false
}
for _, cidr := range this.trustedCIDRs {
if cidr.Contains(ip) {
return true
}
}
return false
}
func (this *Engine) serveError(c *Context, code int, defaultMessage []byte) {
c.writermem.status = code
c.Next()
if c.writermem.Written() {
return
}
if c.writermem.Status() == code {
c.writermem.Header()["Content-Type"] = mimePlain
_, err := c.Writer.Write(defaultMessage)
if err != nil {
this.sys.Errorf("[SYS-Gin] cannot write message to writer during serve error: %v", err)
}
return
}
c.writermem.WriteHeaderNow()
}
func (this *Engine) redirectFixedPath(c *Context, root *node, trailingSlash bool) bool {
req := c.Request
rPath := req.URL.Path
if fixedPath, ok := root.findCaseInsensitivePath(cleanPath(rPath), trailingSlash); ok {
req.URL.Path = convert.BytesToString(fixedPath)
this.redirectRequest(c)
return true
}
return false
}
func (this *Engine) redirectTrailingSlash(c *Context) {
req := c.Request
p := req.URL.Path
if prefix := path.Clean(c.Request.Header.Get("X-Forwarded-Prefix")); prefix != "." {
p = prefix + "/" + req.URL.Path
}
req.URL.Path = p + "/"
if length := len(p); length > 1 && p[length-1] == '/' {
req.URL.Path = p[:length-1]
}
this.redirectRequest(c)
}
func (this *Engine) redirectRequest(c *Context) {
req := c.Request
rPath := req.URL.Path
rURL := req.URL.String()
code := http.StatusMovedPermanently // Permanent redirect, request with GET method
if req.Method != http.MethodGet {
code = http.StatusTemporaryRedirect
}
this.sys.Debugf("redirecting request %d: %s --> %s", code, rPath, rURL)
http.Redirect(c.Writer, req, rURL, code)
c.writermem.WriteHeaderNow()
}
func (this *Engine) parseTrustedProxies() error {
trustedCIDRs, err := this.prepareTrustedCIDRs()
this.trustedCIDRs = trustedCIDRs
return err
}
func (this *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) {
if this.trustedProxies == nil {
return nil, nil
}
cidr := make([]*net.IPNet, 0, len(this.trustedProxies))
for _, trustedProxy := range this.trustedProxies {
if !strings.Contains(trustedProxy, "/") {
ip := parseIP(trustedProxy)
if ip == nil {
return cidr, &net.ParseError{Type: "IP address", Text: trustedProxy}
}
switch len(ip) {
case net.IPv4len:
trustedProxy += "/32"
case net.IPv6len:
trustedProxy += "/128"
}
}
_, cidrNet, err := net.ParseCIDR(trustedProxy)
if err != nil {
return cidr, err
}
cidr = append(cidr, cidrNet)
}
return cidr, nil
}
func (this *Engine) allocateContext() *Context {
v := make(Params, 0, this.maxParams)
skippedNodes := make([]skippedNode, 0, this.maxSections)
return &Context{Sys: this.sys, engine: this, params: &v, skippedNodes: &skippedNodes}
}
//日志接口-------------------------------------------------------------
func (this *Engine) debugPrintLoadTemplate(tmpl *template.Template) {
if this.sys.Debug() {
var buf strings.Builder
for _, tmpl := range tmpl.Templates() {
buf.WriteString("\t- ")
buf.WriteString(tmpl.Name())
buf.WriteString("\n")
}
format := "Loaded HTML Templates (%d): \n%s\n"
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
this.sys.Debugf(format, len(tmpl.Templates()), buf.String())
}
}

View File

@ -0,0 +1,199 @@
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package engine
import (
"encoding/json"
"encoding/xml"
"fmt"
"reflect"
"strings"
)
// H is a shortcut for map[string]interface{}
type H map[string]interface{}
// MarshalXML allows type H to be used with xml.Marshal.
func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name = xml.Name{
Space: "",
Local: "map",
}
if err := e.EncodeToken(start); err != nil {
return err
}
for key, value := range h {
elem := xml.StartElement{
Name: xml.Name{Space: "", Local: key},
Attr: []xml.Attr{},
}
if err := e.EncodeElement(value, elem); err != nil {
return err
}
}
return e.EncodeToken(xml.EndElement{Name: start.Name})
}
// ErrorType is an unsigned 64-bit error code as defined in the gin spec.
type ErrorType uint64
const (
// ErrorTypeBind is used when Context.Bind() fails.
ErrorTypeBind ErrorType = 1 << 63
// ErrorTypeRender is used when Context.Render() fails.
ErrorTypeRender ErrorType = 1 << 62
// ErrorTypePrivate indicates a private error.
ErrorTypePrivate ErrorType = 1 << 0
// ErrorTypePublic indicates a public error.
ErrorTypePublic ErrorType = 1 << 1
// ErrorTypeAny indicates any other error.
ErrorTypeAny ErrorType = 1<<64 - 1
// ErrorTypeNu indicates any other error.
ErrorTypeNu = 2
)
// Error represents a error's specification.
type Error struct {
Err error
Type ErrorType
Meta interface{}
}
type errorMsgs []*Error
var _ error = &Error{}
// SetType sets the error's type.
func (msg *Error) SetType(flags ErrorType) *Error {
msg.Type = flags
return msg
}
// SetMeta sets the error's meta data.
func (msg *Error) SetMeta(data interface{}) *Error {
msg.Meta = data
return msg
}
// JSON creates a properly formatted JSON
func (msg *Error) JSON() interface{} {
jsonData := H{}
if msg.Meta != nil {
value := reflect.ValueOf(msg.Meta)
switch value.Kind() {
case reflect.Struct:
return msg.Meta
case reflect.Map:
for _, key := range value.MapKeys() {
jsonData[key.String()] = value.MapIndex(key).Interface()
}
default:
jsonData["meta"] = msg.Meta
}
}
if _, ok := jsonData["error"]; !ok {
jsonData["error"] = msg.Error()
}
return jsonData
}
// MarshalJSON implements the json.Marshaller interface.
func (msg *Error) MarshalJSON() ([]byte, error) {
return json.Marshal(msg.JSON())
}
// Error implements the error interface.
func (msg Error) Error() string {
return msg.Err.Error()
}
// IsType judges one error.
func (msg *Error) IsType(flags ErrorType) bool {
return (msg.Type & flags) > 0
}
// Unwrap returns the wrapped error, to allow interoperability with errors.Is(), errors.As() and errors.Unwrap()
func (msg *Error) Unwrap() error {
return msg.Err
}
// ByType returns a readonly copy filtered the byte.
// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic.
func (a errorMsgs) ByType(typ ErrorType) errorMsgs {
if len(a) == 0 {
return nil
}
if typ == ErrorTypeAny {
return a
}
var result errorMsgs
for _, msg := range a {
if msg.IsType(typ) {
result = append(result, msg)
}
}
return result
}
// Last returns the last error in the slice. It returns nil if the array is empty.
// Shortcut for errors[len(errors)-1].
func (a errorMsgs) Last() *Error {
if length := len(a); length > 0 {
return a[length-1]
}
return nil
}
// Errors returns an array with all the error messages.
// Example:
// c.Error(errors.New("first"))
// c.Error(errors.New("second"))
// c.Error(errors.New("third"))
// c.Errors.Errors() // == []string{"first", "second", "third"}
func (a errorMsgs) Errors() []string {
if len(a) == 0 {
return nil
}
errorStrings := make([]string, len(a))
for i, err := range a {
errorStrings[i] = err.Error()
}
return errorStrings
}
func (a errorMsgs) JSON() interface{} {
switch length := len(a); length {
case 0:
return nil
case 1:
return a.Last().JSON()
default:
jsonData := make([]interface{}, length)
for i, err := range a {
jsonData[i] = err.JSON()
}
return jsonData
}
}
// MarshalJSON implements the json.Marshaller interface.
func (a errorMsgs) MarshalJSON() ([]byte, error) {
return json.Marshal(a.JSON())
}
func (a errorMsgs) String() string {
if len(a) == 0 {
return ""
}
var buffer strings.Builder
for i, msg := range a {
fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)
if msg.Meta != nil {
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
}
}
return buffer.String()
}

26
lego/sys/gin/engine/fs.go Normal file
View File

@ -0,0 +1,26 @@
package engine
import "net/http"
type onlyFilesFS struct {
fs http.FileSystem
}
type neuteredReaddirFile struct {
http.File
}
func Dir(root string, listDirectory bool) http.FileSystem {
fs := http.Dir(root)
if listDirectory {
return fs
}
return &onlyFilesFS{fs}
}
func (fs onlyFilesFS) Open(name string) (http.File, error) {
f, err := fs.fs.Open(name)
if err != nil {
return nil, err
}
return neuteredReaddirFile{f}, nil
}

View File

@ -0,0 +1,95 @@
package engine
import (
"bufio"
"net"
"net/http"
"go_dreamfactory/lego/sys/log"
)
const (
noWritten = -1
defaultStatus = http.StatusOK
)
type IResponseWriter interface {
http.ResponseWriter
http.Hijacker
http.Flusher
http.CloseNotifier
/*
返回当前请求的 HTTP 响应状态码
*/
Status() int
/*
大小返回已经写入响应 http 正文的字节数
*/
Size() int
/*
WriteHeaderNow 强制写入 http 标头状态码 + 标头
*/
WriteHeaderNow()
}
type ResponseWriter struct {
http.ResponseWriter
log log.Ilogf
size int
status int
}
func (this *ResponseWriter) reset(writer http.ResponseWriter) {
this.ResponseWriter = writer
this.size = noWritten
this.status = defaultStatus
}
func (this *ResponseWriter) WriteHeader(code int) {
if code > 0 && this.status != code {
if this.Written() {
this.log.Warnf("Headers were already written. Wanted to override status code %d with %d", this.status, code)
}
this.status = code
}
}
func (this *ResponseWriter) Status() int {
return this.status
}
func (this *ResponseWriter) Size() int {
return this.size
}
func (this *ResponseWriter) Written() bool {
return this.size != noWritten
}
// Hijack implements the http.Hijacker interface.
func (this *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if this.size < 0 {
this.size = 0
}
return this.ResponseWriter.(http.Hijacker).Hijack()
}
func (this *ResponseWriter) CloseNotify() <-chan bool {
return this.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
func (this *ResponseWriter) Flush() {
this.WriteHeaderNow()
this.ResponseWriter.(http.Flusher).Flush()
}
func (this *ResponseWriter) WriteHeaderNow() {
if !this.Written() {
this.size = 0
this.ResponseWriter.WriteHeader(this.status)
}
}
func (this *ResponseWriter) Pusher() (pusher http.Pusher) {
if pusher, ok := this.ResponseWriter.(http.Pusher); ok {
return pusher
}
return nil
}

View File

@ -0,0 +1,169 @@
package engine
import (
"net/http"
"path"
"regexp"
"strings"
)
var (
regEnLetter = regexp.MustCompile("^[A-Z]+$")
anyMethods = []string{
http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch,
http.MethodHead, http.MethodOptions, http.MethodDelete, http.MethodConnect,
http.MethodTrace,
}
)
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
func (this *RouterGroup) BasePath() string {
return this.basePath
}
func (this *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
this.Handlers = append(this.Handlers, middleware...)
return this.returnObj()
}
func (this *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) IRoutes {
return &RouterGroup{
Handlers: this.combineHandlers(handlers),
basePath: this.calculateAbsolutePath(relativePath),
engine: this.engine,
}
}
func (this *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
if matched := regEnLetter.MatchString(httpMethod); !matched {
panic("http method " + httpMethod + " is not valid")
}
return this.handle(httpMethod, relativePath, handlers)
}
func (this *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodPost, relativePath, handlers)
}
func (this *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodGet, relativePath, handlers)
}
func (this *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodDelete, relativePath, handlers)
}
func (this *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodPatch, relativePath, handlers)
}
func (this *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodPut, relativePath, handlers)
}
func (this *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodOptions, relativePath, handlers)
}
func (this *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes {
return this.handle(http.MethodHead, relativePath, handlers)
}
func (this *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes {
for _, method := range anyMethods {
this.handle(method, relativePath, handlers)
}
return this.returnObj()
}
func (this *RouterGroup) StaticFile(relativePath, filepath string) IRoutes {
return this.staticFileHandler(relativePath, func(c *Context) {
c.File(filepath)
})
}
func (this *RouterGroup) StaticFileFS(relativePath, filepath string, fs http.FileSystem) IRoutes {
return this.staticFileHandler(relativePath, func(c *Context) {
c.FileFromFS(filepath, fs)
})
}
func (this *RouterGroup) Static(relativePath, root string) IRoutes {
return this.StaticFS(relativePath, Dir(root, false))
}
func (this *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes {
if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static folder")
}
handler := this.createStaticHandler(relativePath, fs)
urlPattern := path.Join(relativePath, "/*filepath")
// Register GET and HEAD handlers
this.GET(urlPattern, handler)
this.HEAD(urlPattern, handler)
return this.returnObj()
}
func (this *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
absolutePath := this.calculateAbsolutePath(relativePath)
handlers = this.combineHandlers(handlers)
this.engine.addRoute(httpMethod, absolutePath, handlers)
return this.returnObj()
}
func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc {
absolutePath := group.calculateAbsolutePath(relativePath)
fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
return func(c *Context) {
if _, noListing := fs.(*onlyFilesFS); noListing {
c.Writer.WriteHeader(http.StatusNotFound)
}
file := c.Param("filepath")
f, err := fs.Open(file)
if err != nil {
c.Writer.WriteHeader(http.StatusNotFound)
c.handlers = group.engine.noRoute
c.index = -1
return
}
f.Close()
fileServer.ServeHTTP(c.Writer, c.Request)
}
}
func (this *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {
finalSize := len(this.Handlers) + len(handlers)
assert1(finalSize < int(abortIndex), "too many handlers")
mergedHandlers := make(HandlersChain, finalSize)
copy(mergedHandlers, this.Handlers)
copy(mergedHandlers[len(this.Handlers):], handlers)
return mergedHandlers
}
func (this *RouterGroup) calculateAbsolutePath(relativePath string) string {
return joinPaths(this.basePath, relativePath)
}
func (this *RouterGroup) staticFileHandler(relativePath string, handler HandlerFunc) IRoutes {
if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static file")
}
this.GET(relativePath, handler)
this.HEAD(relativePath, handler)
return this.returnObj()
}
func (this *RouterGroup) returnObj() IRoutes {
if this.root {
return this.engine
}
return this
}

838
lego/sys/gin/engine/tree.go Normal file
View File

@ -0,0 +1,838 @@
package engine
import (
"bytes"
"net/url"
"strings"
"unicode"
"unicode/utf8"
"go_dreamfactory/lego/utils/convert"
)
var (
strColon = []byte(":")
strStar = []byte("*")
strSlash = []byte("/")
)
type Param struct {
Key string
Value string
}
type Params []Param
func (ps Params) Get(name string) (string, bool) {
for _, entry := range ps {
if entry.Key == name {
return entry.Value, true
}
}
return "", false
}
func (ps Params) ByName(name string) (va string) {
va, _ = ps.Get(name)
return
}
type nodeType uint8
type nodeValue struct {
handlers HandlersChain
params *Params
tsr bool
fullPath string
}
type skippedNode struct {
path string
node *node
paramsCount int16
}
const (
root nodeType = iota + 1
param
catchAll
)
type node struct {
path string
indices string
wildChild bool
nType nodeType
priority uint32
children []*node // child nodes, at most 1 :param style node at the end of the array
handlers HandlersChain
fullPath string
}
func (n *node) addChild(child *node) {
if n.wildChild && len(n.children) > 0 {
wildcardChild := n.children[len(n.children)-1]
n.children = append(n.children[:len(n.children)-1], child, wildcardChild)
} else {
n.children = append(n.children, child)
}
}
func (n *node) addRoute(path string, handlers HandlersChain) {
fullPath := path
n.priority++
// Empty tree
if len(n.path) == 0 && len(n.children) == 0 {
n.insertChild(path, fullPath, handlers)
n.nType = root
return
}
parentFullPathIndex := 0
walk:
for {
// Find the longest common prefix.
// This also implies that the common prefix contains no ':' or '*'
// since the existing key can't contain those chars.
i := longestCommonPrefix(path, n.path)
// Split edge
if i < len(n.path) {
child := node{
path: n.path[i:],
wildChild: n.wildChild,
indices: n.indices,
children: n.children,
handlers: n.handlers,
priority: n.priority - 1,
fullPath: n.fullPath,
}
n.children = []*node{&child}
// []byte for proper unicode char conversion, see #65
n.indices = convert.BytesToString([]byte{n.path[i]})
n.path = path[:i]
n.handlers = nil
n.wildChild = false
n.fullPath = fullPath[:parentFullPathIndex+i]
}
// Make new node a child of this node
if i < len(path) {
path = path[i:]
c := path[0]
// '/' after param
if n.nType == param && c == '/' && len(n.children) == 1 {
parentFullPathIndex += len(n.path)
n = n.children[0]
n.priority++
continue walk
}
// Check if a child with the next path byte exists
for i, max := 0, len(n.indices); i < max; i++ {
if c == n.indices[i] {
parentFullPathIndex += len(n.path)
i = n.incrementChildPrio(i)
n = n.children[i]
continue walk
}
}
// Otherwise insert it
if c != ':' && c != '*' && n.nType != catchAll {
// []byte for proper unicode char conversion, see #65
n.indices += convert.BytesToString([]byte{c})
child := &node{
fullPath: fullPath,
}
n.addChild(child)
n.incrementChildPrio(len(n.indices) - 1)
n = child
} else if n.wildChild {
// inserting a wildcard node, need to check if it conflicts with the existing wildcard
n = n.children[len(n.children)-1]
n.priority++
// Check if the wildcard matches
if len(path) >= len(n.path) && n.path == path[:len(n.path)] &&
// Adding a child to a catchAll is not possible
n.nType != catchAll &&
// Check for longer wildcard, e.g. :name and :names
(len(n.path) >= len(path) || path[len(n.path)] == '/') {
continue walk
}
// Wildcard conflict
pathSeg := path
if n.nType != catchAll {
pathSeg = strings.SplitN(pathSeg, "/", 2)[0]
}
prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path
panic("'" + pathSeg +
"' in new path '" + fullPath +
"' conflicts with existing wildcard '" + n.path +
"' in existing prefix '" + prefix +
"'")
}
n.insertChild(path, fullPath, handlers)
return
}
// Otherwise add handle to current node
if n.handlers != nil {
panic("handlers are already registered for path '" + fullPath + "'")
}
n.handlers = handlers
n.fullPath = fullPath
return
}
}
func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) {
for {
// Find prefix until first wildcard
wildcard, i, valid := findWildcard(path)
if i < 0 { // No wildcard found
break
}
// The wildcard name must only contain one ':' or '*' character
if !valid {
panic("only one wildcard per path segment is allowed, has: '" +
wildcard + "' in path '" + fullPath + "'")
}
// check if the wildcard has a name
if len(wildcard) < 2 {
panic("wildcards must be named with a non-empty name in path '" + fullPath + "'")
}
if wildcard[0] == ':' { // param
if i > 0 {
// Insert prefix before the current wildcard
n.path = path[:i]
path = path[i:]
}
child := &node{
nType: param,
path: wildcard,
fullPath: fullPath,
}
n.addChild(child)
n.wildChild = true
n = child
n.priority++
// if the path doesn't end with the wildcard, then there
// will be another subpath starting with '/'
if len(wildcard) < len(path) {
path = path[len(wildcard):]
child := &node{
priority: 1,
fullPath: fullPath,
}
n.addChild(child)
n = child
continue
}
// Otherwise we're done. Insert the handle in the new leaf
n.handlers = handlers
return
}
// catchAll
if i+len(wildcard) != len(path) {
panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
}
if len(n.path) > 0 && n.path[len(n.path)-1] == '/' {
pathSeg := strings.SplitN(n.children[0].path, "/", 2)[0]
panic("catch-all wildcard '" + path +
"' in new path '" + fullPath +
"' conflicts with existing path segment '" + pathSeg +
"' in existing prefix '" + n.path + pathSeg +
"'")
}
// currently fixed width 1 for '/'
i--
if path[i] != '/' {
panic("no / before catch-all in path '" + fullPath + "'")
}
n.path = path[:i]
// First node: catchAll node with empty path
child := &node{
wildChild: true,
nType: catchAll,
fullPath: fullPath,
}
n.addChild(child)
n.indices = string('/')
n = child
n.priority++
// second node: node holding the variable
child = &node{
path: path[i:],
nType: catchAll,
handlers: handlers,
priority: 1,
fullPath: fullPath,
}
n.children = []*node{child}
return
}
// If no wildcard was found, simply insert the path and handle
n.path = path
n.handlers = handlers
n.fullPath = fullPath
}
func (n *node) incrementChildPrio(pos int) int {
cs := n.children
cs[pos].priority++
prio := cs[pos].priority
// Adjust position (move to front)
newPos := pos
for ; newPos > 0 && cs[newPos-1].priority < prio; newPos-- {
// Swap node positions
cs[newPos-1], cs[newPos] = cs[newPos], cs[newPos-1]
}
// Build new index char string
if newPos != pos {
n.indices = n.indices[:newPos] + // Unchanged prefix, might be empty
n.indices[pos:pos+1] + // The index char we move
n.indices[newPos:pos] + n.indices[pos+1:] // Rest without char at 'pos'
}
return newPos
}
func (n *node) getValue(path string, params *Params, skippedNodes *[]skippedNode, unescape bool) (value nodeValue) {
var globalParamsCount int16
walk: // Outer loop for walking the tree
for {
prefix := n.path
if len(path) > len(prefix) {
if path[:len(prefix)] == prefix {
path = path[len(prefix):]
// Try all the non-wildcard children first by matching the indices
idxc := path[0]
for i, c := range []byte(n.indices) {
if c == idxc {
// strings.HasPrefix(n.children[len(n.children)-1].path, ":") == n.wildChild
if n.wildChild {
index := len(*skippedNodes)
*skippedNodes = (*skippedNodes)[:index+1]
(*skippedNodes)[index] = skippedNode{
path: prefix + path,
node: &node{
path: n.path,
wildChild: n.wildChild,
nType: n.nType,
priority: n.priority,
children: n.children,
handlers: n.handlers,
fullPath: n.fullPath,
},
paramsCount: globalParamsCount,
}
}
n = n.children[i]
continue walk
}
}
if !n.wildChild {
// If the path at the end of the loop is not equal to '/' and the current node has no child nodes
// the current node needs to roll back to last vaild skippedNode
if path != "/" {
for l := len(*skippedNodes); l > 0; {
skippedNode := (*skippedNodes)[l-1]
*skippedNodes = (*skippedNodes)[:l-1]
if strings.HasSuffix(skippedNode.path, path) {
path = skippedNode.path
n = skippedNode.node
if value.params != nil {
*value.params = (*value.params)[:skippedNode.paramsCount]
}
globalParamsCount = skippedNode.paramsCount
continue walk
}
}
}
// Nothing found.
// We can recommend to redirect to the same URL without a
// trailing slash if a leaf exists for that path.
value.tsr = path == "/" && n.handlers != nil
return
}
// Handle wildcard child, which is always at the end of the array
n = n.children[len(n.children)-1]
globalParamsCount++
switch n.nType {
case param:
// fix truncate the parameter
// tree_test.go line: 204
// Find param end (either '/' or path end)
end := 0
for end < len(path) && path[end] != '/' {
end++
}
// Save param value
if params != nil && cap(*params) > 0 {
if value.params == nil {
value.params = params
}
// Expand slice within preallocated capacity
i := len(*value.params)
*value.params = (*value.params)[:i+1]
val := path[:end]
if unescape {
if v, err := url.QueryUnescape(val); err == nil {
val = v
}
}
(*value.params)[i] = Param{
Key: n.path[1:],
Value: val,
}
}
// we need to go deeper!
if end < len(path) {
if len(n.children) > 0 {
path = path[end:]
n = n.children[0]
continue walk
}
// ... but we can't
value.tsr = len(path) == end+1
return
}
if value.handlers = n.handlers; value.handlers != nil {
value.fullPath = n.fullPath
return
}
if len(n.children) == 1 {
// No handle found. Check if a handle for this path + a
// trailing slash exists for TSR recommendation
n = n.children[0]
value.tsr = (n.path == "/" && n.handlers != nil) || (n.path == "" && n.indices == "/")
}
return
case catchAll:
// Save param value
if params != nil {
if value.params == nil {
value.params = params
}
// Expand slice within preallocated capacity
i := len(*value.params)
*value.params = (*value.params)[:i+1]
val := path
if unescape {
if v, err := url.QueryUnescape(path); err == nil {
val = v
}
}
(*value.params)[i] = Param{
Key: n.path[2:],
Value: val,
}
}
value.handlers = n.handlers
value.fullPath = n.fullPath
return
default:
panic("invalid node type")
}
}
}
if path == prefix {
// If the current path does not equal '/' and the node does not have a registered handle and the most recently matched node has a child node
// the current node needs to roll back to last vaild skippedNode
if n.handlers == nil && path != "/" {
for l := len(*skippedNodes); l > 0; {
skippedNode := (*skippedNodes)[l-1]
*skippedNodes = (*skippedNodes)[:l-1]
if strings.HasSuffix(skippedNode.path, path) {
path = skippedNode.path
n = skippedNode.node
if value.params != nil {
*value.params = (*value.params)[:skippedNode.paramsCount]
}
globalParamsCount = skippedNode.paramsCount
continue walk
}
}
// n = latestNode.children[len(latestNode.children)-1]
}
// We should have reached the node containing the handle.
// Check if this node has a handle registered.
if value.handlers = n.handlers; value.handlers != nil {
value.fullPath = n.fullPath
return
}
// If there is no handle for this route, but this route has a
// wildcard child, there must be a handle for this path with an
// additional trailing slash
if path == "/" && n.wildChild && n.nType != root {
value.tsr = true
return
}
// No handle found. Check if a handle for this path + a
// trailing slash exists for trailing slash recommendation
for i, c := range []byte(n.indices) {
if c == '/' {
n = n.children[i]
value.tsr = (len(n.path) == 1 && n.handlers != nil) ||
(n.nType == catchAll && n.children[0].handlers != nil)
return
}
}
return
}
// Nothing found. We can recommend to redirect to the same URL with an
// extra trailing slash if a leaf exists for that path
value.tsr = path == "/" ||
(len(prefix) == len(path)+1 && prefix[len(path)] == '/' &&
path == prefix[:len(prefix)-1] && n.handlers != nil)
// roll back to last valid skippedNode
if !value.tsr && path != "/" {
for l := len(*skippedNodes); l > 0; {
skippedNode := (*skippedNodes)[l-1]
*skippedNodes = (*skippedNodes)[:l-1]
if strings.HasSuffix(skippedNode.path, path) {
path = skippedNode.path
n = skippedNode.node
if value.params != nil {
*value.params = (*value.params)[:skippedNode.paramsCount]
}
globalParamsCount = skippedNode.paramsCount
continue walk
}
}
}
return
}
}
func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) ([]byte, bool) {
const stackBufSize = 128
// Use a static sized buffer on the stack in the common case.
// If the path is too long, allocate a buffer on the heap instead.
buf := make([]byte, 0, stackBufSize)
if length := len(path) + 1; length > stackBufSize {
buf = make([]byte, 0, length)
}
ciPath := n.findCaseInsensitivePathRec(
path,
buf, // Preallocate enough memory for new path
[4]byte{}, // Empty rune buffer
fixTrailingSlash,
)
return ciPath, ciPath != nil
}
//使用的递归不区分大小写查找函数
func (n *node) findCaseInsensitivePathRec(path string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) []byte {
npLen := len(n.path)
walk: // Outer loop for walking the tree
for len(path) >= npLen && (npLen == 0 || strings.EqualFold(path[1:npLen], n.path[1:])) {
// Add common prefix to result
oldPath := path
path = path[npLen:]
ciPath = append(ciPath, n.path...)
if len(path) == 0 {
// We should have reached the node containing the handle.
// Check if this node has a handle registered.
if n.handlers != nil {
return ciPath
}
// No handle found.
// Try to fix the path by adding a trailing slash
if fixTrailingSlash {
for i, c := range []byte(n.indices) {
if c == '/' {
n = n.children[i]
if (len(n.path) == 1 && n.handlers != nil) ||
(n.nType == catchAll && n.children[0].handlers != nil) {
return append(ciPath, '/')
}
return nil
}
}
}
return nil
}
// If this node does not have a wildcard (param or catchAll) child,
// we can just look up the next child node and continue to walk down
// the tree
if !n.wildChild {
// Skip rune bytes already processed
rb = shiftNRuneBytes(rb, npLen)
if rb[0] != 0 {
// Old rune not finished
idxc := rb[0]
for i, c := range []byte(n.indices) {
if c == idxc {
// continue with child node
n = n.children[i]
npLen = len(n.path)
continue walk
}
}
} else {
// Process a new rune
var rv rune
// Find rune start.
// Runes are up to 4 byte long,
// -4 would definitely be another rune.
var off int
for max := min(npLen, 3); off < max; off++ {
if i := npLen - off; utf8.RuneStart(oldPath[i]) {
// read rune from cached path
rv, _ = utf8.DecodeRuneInString(oldPath[i:])
break
}
}
// Calculate lowercase bytes of current rune
lo := unicode.ToLower(rv)
utf8.EncodeRune(rb[:], lo)
// Skip already processed bytes
rb = shiftNRuneBytes(rb, off)
idxc := rb[0]
for i, c := range []byte(n.indices) {
// Lowercase matches
if c == idxc {
// must use a recursive approach since both the
// uppercase byte and the lowercase byte might exist
// as an index
if out := n.children[i].findCaseInsensitivePathRec(
path, ciPath, rb, fixTrailingSlash,
); out != nil {
return out
}
break
}
}
// If we found no match, the same for the uppercase rune,
// if it differs
if up := unicode.ToUpper(rv); up != lo {
utf8.EncodeRune(rb[:], up)
rb = shiftNRuneBytes(rb, off)
idxc := rb[0]
for i, c := range []byte(n.indices) {
// Uppercase matches
if c == idxc {
// Continue with child node
n = n.children[i]
npLen = len(n.path)
continue walk
}
}
}
}
// Nothing found. We can recommend to redirect to the same URL
// without a trailing slash if a leaf exists for that path
if fixTrailingSlash && path == "/" && n.handlers != nil {
return ciPath
}
return nil
}
n = n.children[0]
switch n.nType {
case param:
// Find param end (either '/' or path end)
end := 0
for end < len(path) && path[end] != '/' {
end++
}
// Add param value to case insensitive path
ciPath = append(ciPath, path[:end]...)
// We need to go deeper!
if end < len(path) {
if len(n.children) > 0 {
// Continue with child node
n = n.children[0]
npLen = len(n.path)
path = path[end:]
continue
}
// ... but we can't
if fixTrailingSlash && len(path) == end+1 {
return ciPath
}
return nil
}
if n.handlers != nil {
return ciPath
}
if fixTrailingSlash && len(n.children) == 1 {
// No handle found. Check if a handle for this path + a
// trailing slash exists
n = n.children[0]
if n.path == "/" && n.handlers != nil {
return append(ciPath, '/')
}
}
return nil
case catchAll:
return append(ciPath, path...)
default:
panic("invalid node type")
}
}
// Nothing found.
// Try to fix the path by adding / removing a trailing slash
if fixTrailingSlash {
if path == "/" {
return ciPath
}
if len(path)+1 == npLen && n.path[len(path)] == '/' &&
strings.EqualFold(path[1:], n.path[1:len(path)]) && n.handlers != nil {
return append(ciPath, n.path...)
}
}
return nil
}
type methodTree struct {
method string
root *node
}
type methodTrees []methodTree
func (trees methodTrees) get(method string) *node {
for _, tree := range trees {
if tree.method == method {
return tree.root
}
}
return nil
}
/*
将数组中的字节向左移动 n 个字节
*/
func shiftNRuneBytes(rb [4]byte, n int) [4]byte {
switch n {
case 0:
return rb
case 1:
return [4]byte{rb[1], rb[2], rb[3], 0}
case 2:
return [4]byte{rb[2], rb[3]}
case 3:
return [4]byte{rb[3]}
default:
return [4]byte{}
}
}
func longestCommonPrefix(a, b string) int {
i := 0
max := min(len(a), len(b))
for i < max && a[i] == b[i] {
i++
}
return i
}
func findWildcard(path string) (wildcard string, i int, valid bool) {
// Find start
for start, c := range []byte(path) {
// A wildcard starts with ':' (param) or '*' (catch-all)
if c != ':' && c != '*' {
continue
}
// Find end and check for invalid characters
valid = true
for end, c := range []byte(path[start+1:]) {
switch c {
case '/':
return path[start : start+1+end], start, valid
case ':', '*':
valid = false
}
}
return path[start:], start, valid
}
return "", -1, false
}
func countParams(path string) uint16 {
var n uint16
s := convert.StringToBytes(path)
n += uint16(bytes.Count(s, strColon))
n += uint16(bytes.Count(s, strStar))
return n
}
func countSections(path string) uint16 {
s := convert.StringToBytes(path)
return uint16(bytes.Count(s, strSlash))
}
func min(a, b int) int {
if a <= b {
return a
}
return b
}

View File

@ -0,0 +1,201 @@
package engine
import (
"net"
"path"
"reflect"
"runtime"
"strings"
"unicode"
)
/*
解析一个 IP 的字符串表示并返回一个 net.IP
最小字节表示如果输入无效则为零
*/
func parseIP(ip string) net.IP {
parsedIP := net.ParseIP(ip)
if ipv4 := parsedIP.To4(); ipv4 != nil {
return ipv4
}
return parsedIP
}
func lastChar(str string) uint8 {
if str == "" {
panic("The length of the string can't be 0")
}
return str[len(str)-1]
}
func assert1(guard bool, text string) {
if !guard {
panic(text)
}
}
func nameOfFunction(f interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}
func joinPaths(absolutePath, relativePath string) string {
if relativePath == "" {
return absolutePath
}
finalPath := path.Join(absolutePath, relativePath)
if lastChar(relativePath) == '/' && lastChar(finalPath) != '/' {
return finalPath + "/"
}
return finalPath
}
func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo {
path += root.path
if len(root.handlers) > 0 {
handlerFunc := root.handlers.Last()
routes = append(routes, RouteInfo{
Method: method,
Path: path,
Handler: nameOfFunction(handlerFunc),
HandlerFunc: handlerFunc,
})
}
for _, child := range root.children {
routes = iterate(path, method, routes, child)
}
return routes
}
func filterFlags(content string) string {
for i, char := range content {
if char == ' ' || char == ';' {
return content[:i]
}
}
return content
}
func cleanPath(p string) string {
const stackBufSize = 128
if p == "" {
return "/"
}
buf := make([]byte, 0, stackBufSize)
n := len(p)
r := 1
w := 1
if p[0] != '/' {
r = 0
if n+1 > stackBufSize {
buf = make([]byte, n+1)
} else {
buf = buf[:n+1]
}
buf[0] = '/'
}
trailing := n > 1 && p[n-1] == '/'
for r < n {
switch {
case p[r] == '/':
r++
case p[r] == '.' && r+1 == n:
trailing = true
r++
case p[r] == '.' && p[r+1] == '/':
r += 2
case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'):
r += 3
if w > 1 {
w--
if len(buf) == 0 {
for w > 1 && p[w] != '/' {
w--
}
} else {
for w > 1 && buf[w] != '/' {
w--
}
}
}
default:
if w > 1 {
bufApp(&buf, p, w, '/')
w++
}
for r < n && p[r] != '/' {
bufApp(&buf, p, w, p[r])
w++
r++
}
}
}
if trailing && w > 1 {
bufApp(&buf, p, w, '/')
w++
}
if len(buf) == 0 {
return p[:w]
}
return string(buf[:w])
}
func bufApp(buf *[]byte, s string, w int, c byte) {
b := *buf
if len(b) == 0 {
// No modification of the original string so far.
// If the next character is the same as in the original string, we do
// not yet have to allocate a buffer.
if s[w] == c {
return
}
// Otherwise use either the stack buffer, if it is large enough, or
// allocate a new buffer on the heap, and copy all previous characters.
length := len(s)
if length > cap(b) {
*buf = make([]byte, length)
} else {
*buf = (*buf)[:length]
}
b = *buf
copy(b, s[:w])
}
b[w] = c
}
func parseAccept(acceptHeader string) []string {
parts := strings.Split(acceptHeader, ",")
out := make([]string, 0, len(parts))
for _, part := range parts {
if i := strings.IndexByte(part, ';'); i > 0 {
part = part[:i]
}
if part = strings.TrimSpace(part); part != "" {
out = append(out, part)
}
}
return out
}
func chooseData(custom, wildcard interface{}) interface{} {
if custom != nil {
return custom
}
if wildcard != nil {
return wildcard
}
panic("negotiation config is invalid")
}
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] > unicode.MaxASCII {
return false
}
}
return true
}

192
lego/sys/gin/gin.go Normal file
View File

@ -0,0 +1,192 @@
package gin
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"go_dreamfactory/lego/sys/gin/engine"
"go_dreamfactory/lego/sys/gin/middleware/logger"
"go_dreamfactory/lego/sys/gin/middleware/recovery"
)
func newSys(options Options) (sys *Gin, err error) {
sys = &Gin{
options: options,
}
sys.engine = engine.NewEngine(sys)
///添加基础中间件
sys.engine.Use(logger.Logger([]string{}), recovery.Recovery())
if options.CertFile != "" && options.KeyFile != "" {
sys.RunTLS(options.ListenPort, options.CertFile, options.KeyFile)
} else {
sys.Run(options.ListenPort)
}
return
}
type Gin struct {
options Options
server *http.Server
engine *engine.Engine
}
func (this *Gin) Run(listenPort int) (err error) {
defer func() {
if err != nil {
this.Errorf("Run err:%v", err)
}
}()
// if this.engine.IsUnsafeTrustedProxies() {
// this.Warnf("You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
// "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
// }
this.Debugf("Listening and serving HTTP on:%d", listenPort)
this.server = &http.Server{
Addr: fmt.Sprintf(":%d", listenPort),
Handler: this.engine.Handler(),
}
go func() {
if err := this.server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
this.Errorf("Run err:%v", err)
}
}()
// err = http.ListenAndServe(fmt.Sprintf(":%d", this.options.ListenPort), this.Handler())
return
}
func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) {
this.Debugf("Listening and serving HTTPS on :%d", listenPort)
defer func() {
if err != nil {
this.Errorf("RunTLS err:%v", err)
}
}()
// if this.engine.IsUnsafeTrustedProxies() {
// this.Warnf("You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
// "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
// }
this.server = &http.Server{
Addr: fmt.Sprintf(":%d", listenPort),
Handler: this.engine.Handler(),
}
go func() {
if err := this.server.ListenAndServeTLS(certFile, keyFile); err != nil && errors.Is(err, http.ErrServerClosed) {
this.Errorf("listen err:%s", err)
}
}()
// err = http.ListenAndServeTLS(addr, certFile, keyFile, this.Handler())
return
}
func (this *Gin) RunListener(listener net.Listener) (err error) {
this.Debugf("Listening and serving HTTP on listener what's bind with address@%s", listener.Addr())
defer func() {
if err != nil {
this.Errorf("Run err:%v", err)
}
}()
// if this.engine.IsUnsafeTrustedProxies() {
// this.Warnf("You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
// "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
// }
err = http.Serve(listener, this.engine.Handler())
return
}
func (this *Gin) Close() (err error) {
if err = this.server.Shutdown(context.Background()); err != nil {
this.Errorf("Close err:%v", err)
}
this.server.Close()
return
}
func (this *Gin) Group(relativePath string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.Group(relativePath, handlers...)
}
func (this *Gin) Use(handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.Use(handlers...)
}
func (this *Gin) Handle(httpMethod string, relativePath string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.Handle(httpMethod, relativePath, handlers...)
}
func (this *Gin) Any(relativePath string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.Any(relativePath, handlers...)
}
func (this *Gin) GET(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.GET(httpMethod, handlers...)
}
func (this *Gin) POST(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.POST(httpMethod, handlers...)
}
func (this *Gin) DELETE(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.DELETE(httpMethod, handlers...)
}
func (this *Gin) PATCH(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return defsys.PATCH(httpMethod, handlers...)
}
func (this *Gin) PUT(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.PUT(httpMethod, handlers...)
}
func (this *Gin) OPTIONS(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.OPTIONS(httpMethod, handlers...)
}
func (this *Gin) HEAD(httpMethod string, handlers ...engine.HandlerFunc) engine.IRoutes {
return this.engine.HEAD(httpMethod, handlers...)
}
func (this *Gin) StaticFile(relativePath string, filepath string) engine.IRoutes {
return this.engine.StaticFile(relativePath, filepath)
}
func (this *Gin) StaticFileFS(relativePath string, filepath string, fs http.FileSystem) engine.IRoutes {
return this.engine.StaticFileFS(relativePath, filepath, fs)
}
func (this *Gin) Static(relativePath string, root string) engine.IRoutes {
return this.engine.Static(relativePath, root)
}
func (this *Gin) StaticFS(relativePath string, fs http.FileSystem) engine.IRoutes {
return this.engine.StaticFS(relativePath, fs)
}
///日志***********************************************************************
func (this *Gin) Debug() bool {
return this.options.Debug
}
func (this *Gin) Debugf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Debugf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Infof(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Infof("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Warnf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Warnf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Errorf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Errorf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Panicf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Panicf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Fatalf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Fatalf("[SYS Gin] "+format, a...)
}
}

View File

@ -0,0 +1,28 @@
/*
解决跨域 中间件
*/
package cross
import (
"net/http"
"go_dreamfactory/lego/sys/gin/engine"
)
func handlerCors() engine.HandlerFunc {
return func(c *engine.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin") //请求头部
if origin != "" {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,X-Token, Accept, Authorization")
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
} //允许类型校验
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
c.Next()
}
}

View File

@ -0,0 +1,83 @@
package jwt
import (
"net/http"
"strings"
"time"
"go_dreamfactory/lego/sys/gin/engine"
"github.com/golang-jwt/jwt"
)
func NewJWT(key string) *JWT {
return &JWT{jwtkey: key}
}
type JWT struct {
jwtkey string
}
// CreateToken 生成token
func (this *JWT) CreateToken(Id string) (string, error) {
expireTime := time.Now().Add(2 * time.Hour) //过期时间
nowTime := time.Now() //当前时间
claims := jwt.StandardClaims{
Id: Id, //用户Id
ExpiresAt: expireTime.Unix(), //过期时间戳
IssuedAt: nowTime.Unix(), //当前时间戳
Issuer: "blogLeo", //颁发者签名
Subject: "userToken", //签名主题
}
tokenStruct := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return tokenStruct.SignedString([]byte(this.jwtkey))
}
// CheckToken 验证token
func (this *JWT) CheckToken(token string) (*jwt.StandardClaims, bool) {
tokenObj, _ := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
return this.jwtkey, nil
})
if key, _ := tokenObj.Claims.(*jwt.StandardClaims); tokenObj.Valid {
return key, true
} else {
return nil, false
}
}
// JwtMiddleware jwt中间件
func (this *JWT) JwtMiddleware() engine.HandlerFunc {
return func(c *engine.Context) {
//从请求头中获取token
tokenStr := c.Request.Header.Get("Authorization")
//用户不存在
if tokenStr == "" {
c.JSON(http.StatusOK, engine.H{"code": 0, "msg": "用户不存在"})
c.Abort() //阻止执行
return
}
//token格式错误
tokenSlice := strings.SplitN(tokenStr, " ", 2)
if len(tokenSlice) != 2 && tokenSlice[0] != "Bearer" {
c.JSON(http.StatusOK, engine.H{"code": 0, "msg": "token格式错误"})
c.Abort() //阻止执行
return
}
//验证token
tokenStruck, ok := this.CheckToken(tokenSlice[1])
if !ok {
c.JSON(http.StatusOK, engine.H{"code": 0, "msg": "token不正确"})
c.Abort() //阻止执行
return
}
//token超时
if time.Now().Unix() > tokenStruck.ExpiresAt {
c.JSON(http.StatusOK, engine.H{"code": 0, "msg": "token过期"})
c.Abort() //阻止执行
return
}
c.Set("UserId", tokenStruck.Id)
c.Next()
}
}

View File

@ -0,0 +1,85 @@
package logger
import (
"fmt"
"net/http"
"time"
"go_dreamfactory/lego/sys/gin/engine"
)
type LogFormatterParams struct {
Request *http.Request
// TimeStamp shows the time after the server returns a response.
TimeStamp time.Time
// StatusCode is HTTP response code.
StatusCode int
// Latency is how much time the server cost to process a certain request.
Latency time.Duration
// ClientIP equals Context's ClientIP method.
ClientIP string
// Method is the HTTP method given to the request.
Method string
// Path is a path the client requests.
Path string
// ErrorMessage is set if error has occurred in processing the request.
ErrorMessage string
// isTerm shows whether gin's output descriptor refers to a terminal.
isTerm bool
// BodySize is the size of the Response Body
BodySize int
// Keys are the keys set on the request's context.
Keys map[string]interface{}
}
func Logger(SkipPaths []string) engine.HandlerFunc {
var skip map[string]struct{}
if length := len(SkipPaths); length > 0 {
skip = make(map[string]struct{}, length)
for _, path := range SkipPaths {
skip[path] = struct{}{}
}
}
return func(c *engine.Context) {
// Start timer
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
// Process request
c.Next()
// Log only when path is not being skipped
if _, ok := skip[path]; !ok {
param := LogFormatterParams{
Request: c.Request,
Keys: c.Keys,
}
// Stop timer
param.TimeStamp = time.Now()
param.Latency = param.TimeStamp.Sub(start)
param.ClientIP = c.ClientIP()
param.Method = c.Request.Method
param.StatusCode = c.Writer.Status()
param.ErrorMessage = c.Errors.ByType(engine.ErrorTypePrivate).String()
param.BodySize = c.Writer.Size()
if raw != "" {
path = path + "?" + raw
}
param.Path = path
c.Sys.Debugf(fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
param.TimeStamp.Format("2006/01/02 - 15:04:05"),
param.StatusCode,
param.Latency,
param.ClientIP,
param.Method,
param.Path,
param.ErrorMessage,
))
}
}
}

View File

@ -0,0 +1,162 @@
package recovery
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"os"
"runtime"
"strings"
"time"
"go_dreamfactory/lego/sys/gin/engine"
)
const (
green = "\033[97;42m"
white = "\033[90;47m"
yellow = "\033[90;43m"
red = "\033[97;41m"
blue = "\033[97;44m"
magenta = "\033[97;45m"
cyan = "\033[97;46m"
reset = "\033[0m"
)
var (
dunno = []byte("???")
centerDot = []byte("·")
dot = []byte(".")
slash = []byte("/")
)
// RecoveryFunc defines the function passable to CustomRecovery.
type RecoveryFunc func(c *engine.Context, err interface{})
func Recovery() engine.HandlerFunc {
return CustomRecoveryWithWriter(defaultHandleRecovery)
}
func defaultHandleRecovery(c *engine.Context, err interface{}) {
c.AbortWithStatus(http.StatusInternalServerError)
}
// CustomRecoveryWithWriter returns a middleware for a given writer that recovers from any panics and calls the provided handle func to handle it.
func CustomRecoveryWithWriter(handle RecoveryFunc) engine.HandlerFunc {
return func(c *engine.Context) {
defer func() {
if err := recover(); err != nil {
// Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace.
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
var se *os.SyscallError
if errors.As(ne, &se) {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
stack := stack(3)
httpRequest, _ := httputil.DumpRequest(c.Request, false)
headers := strings.Split(string(httpRequest), "\r\n")
for idx, header := range headers {
current := strings.Split(header, ":")
if current[0] == "Authorization" {
headers[idx] = current[0] + ": *"
}
}
headersToStr := strings.Join(headers, "\r\n")
if brokenPipe {
c.Sys.Errorf("%s\n%s%s", err, headersToStr, reset)
} else if c.Sys.Debug() {
c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s",
timeFormat(time.Now()), headersToStr, err, stack, reset)
} else {
c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s%s",
timeFormat(time.Now()), err, stack, reset)
}
if brokenPipe {
// If the connection is dead, we can't write a status to it.
c.Error(err.(error)) // nolint: errcheck
c.Abort()
} else {
handle(c, err)
}
}
}()
c.Next()
}
}
// stack returns a nicely formatted stack frame, skipping skip frames.
func stack(skip int) []byte {
buf := new(bytes.Buffer) // the returned data
// As we loop, we open files and read them. These variables record the currently
// loaded file.
var lines [][]byte
var lastFile string
for i := skip; ; i++ { // Skip the expected number of frames
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
// Print this much at least. If we can't find the source, it won't show.
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
if file != lastFile {
data, err := ioutil.ReadFile(file)
if err != nil {
continue
}
lines = bytes.Split(data, []byte{'\n'})
lastFile = file
}
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
}
return buf.Bytes()
}
// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
if n < 0 || n >= len(lines) {
return dunno
}
return bytes.TrimSpace(lines[n])
}
// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
fn := runtime.FuncForPC(pc)
if fn == nil {
return dunno
}
name := []byte(fn.Name())
// The name includes the path name to the package, which is unnecessary
// since the file name is already included. Plus, it has center dots.
// That is, we see
// runtime/debug.*T·ptrmethod
// and want
// *T.ptrmethod
// Also the package path might contain dot (e.g. code.google.com/...),
// so first eliminate the path prefix
if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 {
name = name[lastSlash+1:]
}
if period := bytes.Index(name, dot); period >= 0 {
name = name[period+1:]
}
name = bytes.Replace(name, centerDot, dot, -1)
return name
}
// timeFormat returns a customized time string for logger.
func timeFormat(t time.Time) string {
return t.Format("2006/01/02 - 15:04:05")
}

76
lego/sys/gin/options.go Normal file
View File

@ -0,0 +1,76 @@
package gin
import (
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
ListenPort int //监听端口
CertFile string //tls文件
KeyFile string //tls文件
Debug bool //日志是否开启
Log log.ILog
}
func SetListenPort(v int) Option {
return func(o *Options) {
o.ListenPort = v
}
}
func SetCertFile(v string) Option {
return func(o *Options) {
o.CertFile = v
}
}
func SetKeyFile(v string) Option {
return func(o *Options) {
o.KeyFile = v
}
}
func SetDebug(v bool) Option {
return func(o *Options) {
o.Debug = v
}
}
func SetLog(v log.ILog) Option {
return func(o *Options) {
o.Log = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
ListenPort: 8080,
CertFile: "",
KeyFile: "",
Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
ListenPort: 8080,
CertFile: "",
KeyFile: "",
Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,21 @@
package render
import "net/http"
// Data contains ContentType and bytes data.
type Data struct {
ContentType string
Data []byte
}
// Render (Data) writes data with custom ContentType.
func (r Data) Render(w http.ResponseWriter) (err error) {
r.WriteContentType(w)
_, err = w.Write(r.Data)
return
}
// WriteContentType (Data) writes custom ContentType.
func (r Data) WriteContentType(w http.ResponseWriter) {
writeContentType(w, []string{r.ContentType})
}

View File

@ -0,0 +1,84 @@
package render
import (
"html/template"
"net/http"
)
var htmlContentType = []string{"text/html; charset=utf-8"}
/*
Delims 表示一组用于 HTML 模板渲染的左右分隔符
*/
type Delims struct {
// Left delimiter, defaults to {{.
Left string
// Right delimiter, defaults to }}.
Right string
}
/*
包含模板引用及其分隔符
*/
type HTMLRender interface {
Instance(string, interface{}) Render
}
type HTMLProduction struct {
Template *template.Template
Delims Delims
}
func (r HTMLProduction) Instance(name string, data interface{}) Render {
return HTML{
Template: r.Template,
Name: name,
Data: data,
}
}
type HTMLDebug struct {
Files []string
Glob string
Delims Delims
FuncMap template.FuncMap
}
// 返回一个实现Render接口的HTML实例。
func (r HTMLDebug) Instance(name string, data interface{}) Render {
return HTML{
Template: r.loadTemplate(),
Name: name,
Data: data,
}
}
func (r HTMLDebug) loadTemplate() *template.Template {
if r.FuncMap == nil {
r.FuncMap = template.FuncMap{}
}
if len(r.Files) > 0 {
return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...))
}
if r.Glob != "" {
return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob))
}
panic("the HTML debug render was created without files or glob pattern")
}
type HTML struct {
Template *template.Template
Name string
Data interface{}
}
func (r HTML) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
if r.Name == "" {
return r.Template.Execute(w, r.Data)
}
return r.Template.ExecuteTemplate(w, r.Name, r.Data)
}
func (r HTML) WriteContentType(w http.ResponseWriter) {
writeContentType(w, htmlContentType)
}

189
lego/sys/gin/render/json.go Normal file
View File

@ -0,0 +1,189 @@
package render
import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"net/http"
"go_dreamfactory/lego/utils/convert"
)
// JSON contains the given interface object.
type JSON struct {
Data interface{}
}
// IndentedJSON contains the given interface object.
type IndentedJSON struct {
Data interface{}
}
// SecureJSON contains the given interface object and its prefix.
type SecureJSON struct {
Prefix string
Data interface{}
}
// JsonpJSON contains the given interface object its callback.
type JsonpJSON struct {
Callback string
Data interface{}
}
// AsciiJSON contains the given interface object.
type AsciiJSON struct {
Data interface{}
}
// PureJSON contains the given interface object.
type PureJSON struct {
Data interface{}
}
var (
jsonContentType = []string{"application/json; charset=utf-8"}
jsonpContentType = []string{"application/javascript; charset=utf-8"}
jsonASCIIContentType = []string{"application/json"}
)
// Render (JSON) writes data with custom ContentType.
func (r JSON) Render(w http.ResponseWriter) (err error) {
if err = WriteJSON(w, r.Data); err != nil {
panic(err)
}
return
}
// WriteContentType (JSON) writes JSON ContentType.
func (r JSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}
// WriteJSON marshals the given interface object and writes it with custom ContentType.
func WriteJSON(w http.ResponseWriter, obj interface{}) error {
writeContentType(w, jsonContentType)
jsonBytes, err := json.Marshal(obj)
if err != nil {
return err
}
_, err = w.Write(jsonBytes)
return err
}
// Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType.
func (r IndentedJSON) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
jsonBytes, err := json.MarshalIndent(r.Data, "", " ")
if err != nil {
return err
}
_, err = w.Write(jsonBytes)
return err
}
// WriteContentType (IndentedJSON) writes JSON ContentType.
func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}
// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType.
func (r SecureJSON) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
jsonBytes, err := json.Marshal(r.Data)
if err != nil {
return err
}
// if the jsonBytes is array values
if bytes.HasPrefix(jsonBytes, convert.StringToBytes("[")) && bytes.HasSuffix(jsonBytes,
convert.StringToBytes("]")) {
if _, err = w.Write(convert.StringToBytes(r.Prefix)); err != nil {
return err
}
}
_, err = w.Write(jsonBytes)
return err
}
// WriteContentType (SecureJSON) writes JSON ContentType.
func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}
// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType.
func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
r.WriteContentType(w)
ret, err := json.Marshal(r.Data)
if err != nil {
return err
}
if r.Callback == "" {
_, err = w.Write(ret)
return err
}
callback := template.JSEscapeString(r.Callback)
if _, err = w.Write(convert.StringToBytes(callback)); err != nil {
return err
}
if _, err = w.Write(convert.StringToBytes("(")); err != nil {
return err
}
if _, err = w.Write(ret); err != nil {
return err
}
if _, err = w.Write(convert.StringToBytes(");")); err != nil {
return err
}
return nil
}
// WriteContentType (JsonpJSON) writes Javascript ContentType.
func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonpContentType)
}
// Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType.
func (r AsciiJSON) Render(w http.ResponseWriter) (err error) {
r.WriteContentType(w)
ret, err := json.Marshal(r.Data)
if err != nil {
return err
}
var buffer bytes.Buffer
for _, r := range convert.BytesToString(ret) {
cvt := string(r)
if r >= 128 {
cvt = fmt.Sprintf("\\u%04x", int64(r))
}
buffer.WriteString(cvt)
}
_, err = w.Write(buffer.Bytes())
return err
}
// WriteContentType (AsciiJSON) writes JSON ContentType.
func (r AsciiJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonASCIIContentType)
}
// Render (PureJSON) writes custom ContentType and encodes the given interface object.
func (r PureJSON) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
encoder := json.NewEncoder(w)
encoder.SetEscapeHTML(false)
return encoder.Encode(r.Data)
}
// WriteContentType (PureJSON) writes custom ContentType.
func (r PureJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}

View File

@ -0,0 +1,32 @@
package render
import (
"net/http"
"google.golang.org/protobuf/proto"
)
// ProtoBuf contains the given interface object.
type ProtoBuf struct {
Data interface{}
}
var protobufContentType = []string{"application/x-protobuf"}
// Render (ProtoBuf) marshals the given interface object and writes data with custom ContentType.
func (r ProtoBuf) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
bytes, err := proto.Marshal(r.Data.(proto.Message))
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}
// WriteContentType (ProtoBuf) writes ProtoBuf ContentType.
func (r ProtoBuf) WriteContentType(w http.ResponseWriter) {
writeContentType(w, protobufContentType)
}

View File

@ -0,0 +1,44 @@
package render
import (
"io"
"net/http"
"strconv"
)
// Reader contains the IO reader and its length, and custom ContentType and other headers.
type Reader struct {
ContentType string
ContentLength int64
Reader io.Reader
Headers map[string]string
}
// Render (Reader) writes data with custom ContentType and headers.
func (r Reader) Render(w http.ResponseWriter) (err error) {
r.WriteContentType(w)
if r.ContentLength >= 0 {
if r.Headers == nil {
r.Headers = map[string]string{}
}
r.Headers["Content-Length"] = strconv.FormatInt(r.ContentLength, 10)
}
r.writeHeaders(w, r.Headers)
_, err = io.Copy(w, r.Reader)
return
}
// WriteContentType (Reader) writes custom ContentType.
func (r Reader) WriteContentType(w http.ResponseWriter) {
writeContentType(w, []string{r.ContentType})
}
// writeHeaders writes custom Header.
func (r Reader) writeHeaders(w http.ResponseWriter, headers map[string]string) {
header := w.Header()
for k, v := range headers {
if header.Get(k) == "" {
header.Set(k, v)
}
}
}

View File

@ -0,0 +1,25 @@
package render
import (
"fmt"
"net/http"
)
// Redirect contains the http request reference and redirects status code and location.
type Redirect struct {
Code int
Request *http.Request
Location string
}
// Render (Redirect) redirects the http request to new location and writes redirect response.
func (r Redirect) Render(w http.ResponseWriter) error {
if (r.Code < http.StatusMultipleChoices || r.Code > http.StatusPermanentRedirect) && r.Code != http.StatusCreated {
panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code))
}
http.Redirect(w, r.Request, r.Location, r.Code)
return nil
}
// WriteContentType (Redirect) don't write any ContentType.
func (r Redirect) WriteContentType(http.ResponseWriter) {}

View File

@ -0,0 +1,19 @@
package render
import (
"net/http"
)
type Render interface {
// Render 使用自定义 ContentType 写入数据。
Render(http.ResponseWriter) error
// WriteContentType 写入自定义 ContentType。
WriteContentType(w http.ResponseWriter)
}
func writeContentType(w http.ResponseWriter, value []string) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = value
}
}

View File

@ -0,0 +1,37 @@
package render
import (
"fmt"
"net/http"
"go_dreamfactory/lego/utils/convert"
)
// String contains the given interface object slice and its format.
type String struct {
Format string
Data []interface{}
}
var plainContentType = []string{"text/plain; charset=utf-8"}
// Render (String) writes data with custom ContentType.
func (r String) Render(w http.ResponseWriter) error {
return WriteString(w, r.Format, r.Data)
}
// WriteContentType (String) writes Plain ContentType.
func (r String) WriteContentType(w http.ResponseWriter) {
writeContentType(w, plainContentType)
}
// WriteString writes data according to its format and write custom ContentType.
func WriteString(w http.ResponseWriter, format string, data []interface{}) (err error) {
writeContentType(w, plainContentType)
if len(data) > 0 {
_, err = fmt.Fprintf(w, format, data...)
return
}
_, err = w.Write(convert.StringToBytes(format))
return
}

View File

@ -0,0 +1,24 @@
package render
import (
"encoding/xml"
"net/http"
)
// XML contains the given interface object.
type XML struct {
Data interface{}
}
var xmlContentType = []string{"application/xml; charset=utf-8"}
// Render (XML) encodes the given interface object and writes data with custom ContentType.
func (r XML) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
return xml.NewEncoder(w).Encode(r.Data)
}
// WriteContentType (XML) writes XML ContentType for response.
func (r XML) WriteContentType(w http.ResponseWriter) {
writeContentType(w, xmlContentType)
}

View File

@ -0,0 +1,32 @@
package render
import (
"net/http"
"gopkg.in/yaml.v2"
)
// YAML contains the given interface object.
type YAML struct {
Data interface{}
}
var yamlContentType = []string{"application/x-yaml; charset=utf-8"}
// Render (YAML) marshals the given interface object and writes data with custom ContentType.
func (r YAML) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
bytes, err := yaml.Marshal(r.Data)
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}
// WriteContentType (YAML) writes YAML ContentType for response.
func (r YAML) WriteContentType(w http.ResponseWriter) {
writeContentType(w, yamlContentType)
}

42
lego/sys/gin/sys_test.go Normal file
View File

@ -0,0 +1,42 @@
package gin_test
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"testing"
"go_dreamfactory/lego/sys/gin"
"go_dreamfactory/lego/sys/gin/engine"
"go_dreamfactory/lego/sys/log"
)
func Test_sys(t *testing.T) {
if err := log.OnInit(nil); err != nil {
fmt.Printf("log init err:%v", err)
return
}
if sys, err := gin.NewSys(); err != nil {
fmt.Printf("gin init err:%v", err)
} else {
sys.GET("/test", func(c *engine.Context) {
c.JSON(http.StatusOK, "hello")
})
}
//监听外部关闭服务信号
c := make(chan os.Signal, 1)
//添加进程结束信号
signal.Notify(c,
os.Interrupt, //退出信号 ctrl+c退出
syscall.SIGHUP, //终端控制进程结束(终端连接断开)
syscall.SIGINT, //用户发送INTR字符(Ctrl+C)触发
syscall.SIGTERM, //结束程序(可以被捕获、阻塞或忽略)
syscall.SIGQUIT) //用户发送QUIT字符(Ctrl+/)触发
select {
case sig := <-c:
fmt.Println("关闭 signal\n", sig)
}
}

79
lego/sys/log/core.go Normal file
View File

@ -0,0 +1,79 @@
package log
import (
"fmt"
"os"
"strings"
"go_dreamfactory/lego/utils/flietools"
)
type (
LogStrut interface {
ToString() (str string)
}
Field struct {
Key string
Value interface{}
}
Ilogf interface {
Debugf(format string, a ...interface{})
Infof(format string, a ...interface{})
Warnf(format string, a ...interface{})
Errorf(format string, a ...interface{})
Panicf(format string, a ...interface{})
Fatalf(format string, a ...interface{})
}
ILog interface {
Clone(option ...Option) ILog
Debug(msg string, fields ...Field)
Info(msg string, fields ...Field)
Warn(msg string, fields ...Field)
Error(msg string, fields ...Field)
Panic(msg string, fields ...Field)
Fatal(msg string, fields ...Field)
Ilogf
}
)
var (
defsys ILog
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ILog, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func Clone(option ...Option) ILog {
return defsys.Clone(option...)
}
func Debug(msg string, fields ...Field) { defsys.Debug(msg, fields...) }
func Info(msg string, fields ...Field) { defsys.Info(msg, fields...) }
func Warn(msg string, fields ...Field) { defsys.Warn(msg, fields...) }
func Error(msg string, fields ...Field) { defsys.Error(msg, fields...) }
func Panic(msg string, fields ...Field) { defsys.Panic(msg, fields...) }
func Fatal(msg string, fields ...Field) { defsys.Fatal(msg, fields...) }
func Debugf(format string, a ...interface{}) { defsys.Debugf(format, a...) }
func Infof(format string, a ...interface{}) { defsys.Infof(format, a...) }
func Warnf(format string, a ...interface{}) { defsys.Warnf(format, a...) }
func Errorf(format string, a ...interface{}) { defsys.Errorf(format, a...) }
func Panicf(format string, a ...interface{}) { defsys.Panicf(format, a...) }
func Fatalf(format string, a ...interface{}) { defsys.Fatalf(format, a...) }
//创建日志文件
func createlogfile(logpath string) error {
logdir := string(logpath[0:strings.LastIndex(logpath, "/")])
if !flietools.IsExist(logdir) {
err := os.MkdirAll(logdir, os.ModePerm)
if err != nil {
return fmt.Errorf("创建日志路径失败 1" + err.Error())
}
}
return nil
}

114
lego/sys/log/options.go Normal file
View File

@ -0,0 +1,114 @@
package log
import (
"go_dreamfactory/lego/utils/mapstructure"
)
type Loglevel int8
const (
DebugLevel Loglevel = iota
InfoLevel
WarnLevel
ErrorLevel
PanicLevel
FatalLevel
)
type LogEncoder int8
const (
Console LogEncoder = iota
JSON
)
type Option func(*Options)
type Options struct {
FileName string //日志文件名包含
Loglevel Loglevel //日志输出级别
Debugmode bool //是否debug模式
Encoder LogEncoder //日志输出样式
Loglayer int //日志堆栈信息打印层级
LogMaxSize int //每个日志文件最大尺寸 单位 M 默认 1024M
LogMaxBackups int //最多保留备份个数 默认 10个
LogMaxAge int //文件最多保存多少天 默认 7天
}
func SetFileName(v string) Option {
return func(o *Options) {
o.FileName = v
}
}
func SetLoglevel(v Loglevel) Option {
return func(o *Options) {
o.Loglevel = v
}
}
func SetDebugMode(v bool) Option {
return func(o *Options) {
o.Debugmode = v
}
}
func SetEncoder(v LogEncoder) Option {
return func(o *Options) {
o.Encoder = v
}
}
func SetLoglayer(v int) Option {
return func(o *Options) {
o.Loglayer = v
}
}
func SetLogMaxSize(v int) Option {
return func(o *Options) {
o.LogMaxSize = v
}
}
func SetLogMaxBackups(v int) Option {
return func(o *Options) {
o.LogMaxBackups = v
}
}
func SetLogMaxAge(v int) Option {
return func(o *Options) {
o.LogMaxAge = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
FileName: "./lego.log",
Loglevel: WarnLevel,
Debugmode: false,
Encoder: Console,
Loglayer: 2,
LogMaxSize: 1024,
LogMaxBackups: 10,
LogMaxAge: 7,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
FileName: "./lego.log",
Loglevel: WarnLevel,
Debugmode: false,
Loglayer: 2,
LogMaxSize: 1024,
LogMaxBackups: 10,
LogMaxAge: 7,
}
for _, o := range opts {
o(&options)
}
return options
}

18
lego/sys/log/sys_test.go Normal file
View File

@ -0,0 +1,18 @@
package log_test
import (
"testing"
"go_dreamfactory/lego/sys/log"
)
func Test_sys(t *testing.T) {
if err := log.OnInit(map[string]interface{}{
"FileName": "./test.log",
"Loglevel": log.FatalLevel,
"Debugmode": true,
"Loglayer": 2,
}); err == nil {
log.Infof("测试日志接口代码!")
}
}

190
lego/sys/log/zaplog.go Normal file
View File

@ -0,0 +1,190 @@
package log
import (
"os"
"time"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func newSys(options Options) (sys *Logger, err error) {
createlogfile(options.FileName)
var allCore []zapcore.Core
hook := lumberjack.Logger{
Filename: options.FileName, //日志文件路径
MaxSize: options.LogMaxSize, //每个日志文件保存的最大尺寸 单位M
MaxBackups: options.LogMaxBackups, //最多保留备份个数
MaxAge: options.LogMaxAge, //文件最多保存多少天
Compress: false, //是否压缩 disabled by default
LocalTime: true, //使用本地时间
}
var level zapcore.Level
switch options.Loglevel {
case DebugLevel:
level = zap.DebugLevel
case InfoLevel:
level = zap.InfoLevel
case WarnLevel:
level = zap.WarnLevel
case ErrorLevel:
level = zap.ErrorLevel
case PanicLevel:
level = zap.PanicLevel
case FatalLevel:
level = zap.FatalLevel
default:
level = zap.InfoLevel
}
fileWriter := zapcore.AddSync(&hook)
consoleDebugging := zapcore.Lock(os.Stdout)
var encoderConfig zapcore.EncoderConfig
timeFormat := func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006/01/02 15:04:05.000"))
}
_, err = os.OpenFile(options.FileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
return
}
if options.Debugmode {
//重新生成文件
encoderConfig = zap.NewDevelopmentEncoderConfig()
encoderConfig.EncodeTime = timeFormat
allCore = append(allCore, zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), consoleDebugging, level))
} else {
encoderConfig = zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = timeFormat
}
if options.Encoder == Console {
allCore = append(allCore, zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), fileWriter, level))
} else {
allCore = append(allCore, zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), fileWriter, level))
}
core := zapcore.NewTee(allCore...)
tlog := zap.New(core).WithOptions(zap.AddCaller(), zap.AddCallerSkip(options.Loglayer))
sys = &Logger{
core: core,
tlog: tlog,
log: tlog.Sugar(),
}
return
}
type Logger struct {
core zapcore.Core
tlog *zap.Logger
log *zap.SugaredLogger
}
func FieldTozapField(fields ...Field) (fds []zap.Field) {
fds = make([]zap.Field, 0)
for _, v := range fields {
field := zap.Field{Key: v.Key}
switch v.Value.(type) {
case []byte:
field.Type = zapcore.BinaryType
field.Interface = v.Value
case bool:
field.Type = zapcore.BoolType
if v.Value.(bool) {
field.Integer = 1
} else {
field.Integer = 0
}
case byte:
field.Type = zapcore.Uint8Type
field.Integer = int64(v.Value.(byte))
case time.Duration:
field.Type = zapcore.DurationType
field.Integer = int64(v.Value.(time.Duration))
case float64:
field.Type = zapcore.Float64Type
field.Integer = v.Value.(int64)
case float32:
field.Type = zapcore.Float32Type
field.Integer = v.Value.(int64)
case int64:
field.Type = zapcore.Int64Type
field.Integer = v.Value.(int64)
case uint64:
field.Type = zapcore.Uint64Type
field.Integer = int64(v.Value.(uint64))
case int32:
field.Type = zapcore.Int32Type
field.Integer = int64(v.Value.(int32))
case uint32:
field.Type = zapcore.Uint64Type
field.Integer = int64(v.Value.(uint32))
case int16:
field.Type = zapcore.Int16Type
field.Integer = int64(v.Value.(int16))
case uint16:
field.Type = zapcore.Uint64Type
field.Integer = int64(v.Value.(uint16))
case int8:
field.Type = zapcore.Int8Type
field.Integer = int64(v.Value.(int8))
case string:
field.Type = zapcore.StringType
field.String = v.Value.(string)
case LogStrut:
field.Type = zapcore.StringType
field.String = v.Value.(LogStrut).ToString()
default:
field.Type = zapcore.UnknownType
field.Interface = v.Value
}
fds = append(fds, field)
}
return
}
func (this *Logger) Clone(option ...Option) (sys ILog) {
options := newOptionsByOption(option...)
tlog := zap.New(this.core).WithOptions(zap.AddCaller(), zap.AddCallerSkip(options.Loglayer))
sys = &Logger{
core: this.core,
tlog: tlog,
log: tlog.Sugar(),
}
return
}
func (this *Logger) Debug(msg string, fields ...Field) {
this.tlog.Debug(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Info(msg string, fields ...Field) {
this.tlog.Info(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Warn(msg string, fields ...Field) {
this.tlog.Warn(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Error(msg string, fields ...Field) {
this.tlog.Error(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Panic(msg string, fields ...Field) {
this.tlog.Panic(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Fatal(msg string, fields ...Field) {
this.tlog.Fatal(msg, FieldTozapField(fields...)...)
}
func (this *Logger) Debugf(format string, a ...interface{}) {
this.log.Debugf(format, a...)
}
func (this *Logger) Infof(format string, a ...interface{}) {
this.log.Infof(format, a...)
}
func (this *Logger) Warnf(format string, a ...interface{}) {
this.log.Warnf(format, a...)
}
func (this *Logger) Errorf(format string, a ...interface{}) {
this.log.Errorf(format, a...)
}
func (this *Logger) Panicf(format string, a ...interface{}) {
this.log.Panicf(format, a...)
}
func (this *Logger) Fatalf(format string, a ...interface{}) {
this.log.Fatalf(format, a...)
}

148
lego/sys/mgo/core.go Normal file
View File

@ -0,0 +1,148 @@
package mgo
import (
"context"
"go_dreamfactory/lego/core"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type (
ISys interface {
Close() (err error)
ListCollectionNames(filter interface{}, opts ...*options.ListCollectionsOptions) ([]string, error)
Collection(sqltable core.SqlTable) *mongo.Collection
CreateIndex(sqltable core.SqlTable, model mongo.IndexModel, opts ...*options.CreateIndexesOptions) (string, error)
DeleteIndex(sqltable core.SqlTable, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error)
UseSession(fn func(sessionContext mongo.SessionContext) error) error
CountDocuments(sqltable core.SqlTable, filter interface{}, opts ...*options.CountOptions) (int64, error)
CountDocumentsByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.CountOptions) (int64, error)
Find(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error)
FindByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error)
FindOne(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult
FindOneAndUpdate(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) *mongo.SingleResult
InsertOne(sqltable core.SqlTable, data interface{}, opts ...*options.InsertOneOptions) (*mongo.InsertOneResult, error)
InsertMany(sqltable core.SqlTable, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error)
InsertManyByCtx(sqltable core.SqlTable, ctx context.Context, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error)
UpdateOne(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error)
UpdateMany(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error)
UpdateManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error)
FindOneAndDelete(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneAndDeleteOptions) *mongo.SingleResult
DeleteOne(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error)
DeleteMany(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error)
DeleteManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error)
Aggregate(sqltable core.SqlTable, pipeline interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error)
}
)
var (
MongodbNil = mongo.ErrNoDocuments //数据为空错误
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func Close() (err error) {
return defsys.Close()
}
func ListCollectionNames(filter interface{}, opts ...*options.ListCollectionsOptions) ([]string, error) {
return defsys.ListCollectionNames(filter, opts...)
}
func Collection(sqltable core.SqlTable) *mongo.Collection {
return defsys.Collection(sqltable)
}
func CreateIndex(sqltable core.SqlTable, model mongo.IndexModel, opts ...*options.CreateIndexesOptions) (string, error) {
return defsys.CreateIndex(sqltable, model, opts...)
}
func DeleteIndex(sqltable core.SqlTable, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error) {
return defsys.DeleteIndex(sqltable, name, opts...)
}
func UseSession(fn func(sessionContext mongo.SessionContext) error) error {
return defsys.UseSession(fn)
}
func CountDocuments(sqltable core.SqlTable, filter interface{}, opts ...*options.CountOptions) (int64, error) {
return defsys.CountDocuments(sqltable, filter, opts...)
}
func CountDocumentsByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.CountOptions) (int64, error) {
return defsys.CountDocumentsByCtx(sqltable, ctx, filter, opts...)
}
func Find(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error) {
return defsys.Find(sqltable, filter, opts...)
}
func FindOne(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult {
return defsys.FindOne(sqltable, filter, opts...)
}
func FindByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error) {
return defsys.FindByCtx(sqltable, ctx, filter, opts...)
}
func FindOneAndUpdate(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) *mongo.SingleResult {
return defsys.FindOneAndUpdate(sqltable, filter, update, opts...)
}
func InsertOne(sqltable core.SqlTable, data interface{}, opts ...*options.InsertOneOptions) (*mongo.InsertOneResult, error) {
return defsys.InsertOne(sqltable, data, opts...)
}
func InsertMany(sqltable core.SqlTable, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error) {
return defsys.InsertMany(sqltable, data, opts...)
}
func InsertManyByCtx(sqltable core.SqlTable, ctx context.Context, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error) {
return defsys.InsertManyByCtx(sqltable, ctx, data, opts...)
}
func UpdateOne(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return defsys.UpdateOne(sqltable, filter, update, opts...)
}
func UpdateMany(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return defsys.UpdateMany(sqltable, filter, update, opts...)
}
func UpdateManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return defsys.UpdateManyByCtx(sqltable, ctx, filter, update, opts...)
}
func FindOneAndDelete(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneAndDeleteOptions) *mongo.SingleResult {
return defsys.FindOneAndDelete(sqltable, filter, opts...)
}
func DeleteOne(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return defsys.DeleteOne(sqltable, filter, opts...)
}
func DeleteMany(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return defsys.DeleteMany(sqltable, filter, opts...)
}
func DeleteManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return defsys.DeleteManyByCtx(sqltable, ctx, filter, opts...)
}
func Aggregate(sqltable core.SqlTable, pipeline interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error) {
return defsys.Aggregate(sqltable, pipeline, opts...)
}

152
lego/sys/mgo/mgo.go Normal file
View File

@ -0,0 +1,152 @@
package mgo
import (
"context"
"fmt"
"time"
"go_dreamfactory/lego/core"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
"go.mongodb.org/mongo-driver/mongo/readpref"
"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
func newSys(options Options) (sys *Mongodb, err error) {
sys = &Mongodb{options: options}
err = sys.init()
return
}
type Mongodb struct {
options Options
Client *mongo.Client
Database *mongo.Database
}
func (this *Mongodb) init() (err error) {
want, err := readpref.New(readpref.SecondaryMode) //表示只使用辅助节点
if err != nil {
return fmt.Errorf("数据库设置辅助节点 err=%s", err.Error())
}
wc := writeconcern.New(writeconcern.WMajority())
readconcern.Majority()
//链接mongo服务
opt := options.Client().ApplyURI(this.options.MongodbUrl)
opt.SetLocalThreshold(3 * time.Second) //只使用与mongo操作耗时小于3秒的
opt.SetMaxConnIdleTime(5 * time.Second) //指定连接可以保持空闲的最大毫秒数
opt.SetMaxPoolSize(this.options.MaxPoolSize) //使用最大的连接数
opt.SetReadPreference(want) //表示只使用辅助节点
opt.SetReadConcern(readconcern.Majority()) //指定查询应返回实例的最新数据确认为,已写入副本集中的大多数成员
opt.SetWriteConcern(wc) //请求确认写操作传播到大多数mongod实例
if client, err := mongo.Connect(this.getContext(), opt); err != nil {
return fmt.Errorf("连接数据库错误 err=%s", err.Error())
} else {
this.Client = client
if err = client.Ping(this.getContext(), readpref.Primary()); err != nil {
return fmt.Errorf("数据库不可用 err=%s", err.Error())
}
this.Database = client.Database(this.options.MongodbDatabase)
}
return
}
func (this *Mongodb) Close() (err error) {
err = this.Client.Disconnect(this.getContext())
return
}
func (this *Mongodb) ListCollectionNames(filter interface{}, opts ...*options.ListCollectionsOptions) ([]string, error) {
return this.Database.ListCollectionNames(this.getContext(), filter, opts...)
}
func (this *Mongodb) Collection(sqltable core.SqlTable) *mongo.Collection {
return this.Client.Database(this.options.MongodbDatabase).Collection(string(sqltable))
}
func (this *Mongodb) getContext() (ctx context.Context) {
ctx, _ = context.WithTimeout(context.Background(), this.options.TimeOut)
return
}
func (this *Mongodb) CreateIndex(sqltable core.SqlTable, model mongo.IndexModel, opts ...*options.CreateIndexesOptions) (string, error) {
return this.Collection(sqltable).Indexes().CreateOne(this.getContext(), model, opts...)
}
func (this *Mongodb) DeleteIndex(sqltable core.SqlTable, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error) {
return this.Collection(sqltable).Indexes().DropOne(this.getContext(), name, opts...)
}
func (this *Mongodb) UseSession(fn func(sessionContext mongo.SessionContext) error) error {
return this.Client.UseSession(this.getContext(), fn)
}
func (this *Mongodb) CountDocuments(sqltable core.SqlTable, filter interface{}, opts ...*options.CountOptions) (int64, error) {
return this.Collection(sqltable).CountDocuments(this.getContext(), filter, opts...)
}
func (this *Mongodb) CountDocumentsByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.CountOptions) (int64, error) {
return this.Collection(sqltable).CountDocuments(ctx, filter, opts...)
}
func (this *Mongodb) Find(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error) {
return this.Collection(sqltable).Find(this.getContext(), filter, opts...)
}
func (this *Mongodb) FindByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.FindOptions) (*mongo.Cursor, error) {
return this.Collection(sqltable).Find(ctx, filter, opts...)
}
func (this *Mongodb) FindOne(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult {
return this.Collection(sqltable).FindOne(this.getContext(), filter, opts...)
}
func (this *Mongodb) FindOneAndUpdate(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) *mongo.SingleResult {
return this.Collection(sqltable).FindOneAndUpdate(this.getContext(), filter, update, opts...)
}
func (this *Mongodb) InsertOne(sqltable core.SqlTable, data interface{}, opts ...*options.InsertOneOptions) (*mongo.InsertOneResult, error) {
return this.Collection(sqltable).InsertOne(this.getContext(), data, opts...)
}
func (this *Mongodb) InsertMany(sqltable core.SqlTable, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error) {
return this.Collection(sqltable).InsertMany(this.getContext(), data, opts...)
}
func (this *Mongodb) InsertManyByCtx(sqltable core.SqlTable, ctx context.Context, data []interface{}, opts ...*options.InsertManyOptions) (*mongo.InsertManyResult, error) {
return this.Collection(sqltable).InsertMany(ctx, data, opts...)
}
func (this *Mongodb) UpdateOne(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return this.Collection(sqltable).UpdateOne(this.getContext(), filter, update, opts...)
}
func (this *Mongodb) UpdateMany(sqltable core.SqlTable, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return this.Collection(sqltable).UpdateMany(this.getContext(), filter, update, opts...)
}
func (this *Mongodb) UpdateManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
return this.Collection(sqltable).UpdateMany(ctx, filter, update, opts...)
}
func (this *Mongodb) FindOneAndDelete(sqltable core.SqlTable, filter interface{}, opts ...*options.FindOneAndDeleteOptions) *mongo.SingleResult {
return this.Collection(sqltable).FindOneAndDelete(this.getContext(), filter, opts...)
}
func (this *Mongodb) DeleteOne(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return this.Collection(sqltable).DeleteOne(this.getContext(), filter, opts...)
}
func (this *Mongodb) DeleteMany(sqltable core.SqlTable, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return this.Collection(sqltable).DeleteMany(this.getContext(), filter, opts...)
}
func (this *Mongodb) DeleteManyByCtx(sqltable core.SqlTable, ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*mongo.DeleteResult, error) {
return this.Collection(sqltable).DeleteMany(ctx, filter, opts...)
}
func (this *Mongodb) Aggregate(sqltable core.SqlTable, pipeline interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error) {
return this.Collection(sqltable).Aggregate(this.getContext(), pipeline, opts...)
}

64
lego/sys/mgo/options.go Normal file
View File

@ -0,0 +1,64 @@
package mgo
import (
"time"
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
MongodbUrl string
MongodbDatabase string
MaxPoolSize uint64
TimeOut time.Duration
}
func SetMongodbUrl(v string) Option {
return func(o *Options) {
o.MongodbUrl = v
}
}
func SetMongodbDatabase(v string) Option {
return func(o *Options) {
o.MongodbDatabase = v
}
}
func SetMaxPoolSize(v uint64) Option {
return func(o *Options) {
o.MaxPoolSize = v
}
}
func SetTimeOut(v time.Duration) Option {
return func(o *Options) {
o.TimeOut = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
MaxPoolSize: 1000,
TimeOut: time.Second * 3,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
MaxPoolSize: 1000,
TimeOut: time.Second * 3,
}
for _, o := range opts {
o(&options)
}
return options
}

214
lego/sys/mgo/sys_test.go Normal file
View File

@ -0,0 +1,214 @@
package mgo_test
import (
"context"
"fmt"
"testing"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/mgo"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/x/bsonx"
)
const (
Sql_UserDataTable core.SqlTable = "userdata" //用户
)
type TestData struct {
Id uint32 `bson:"_id"` //用户id
NiceName string //昵称
Sex int32 //性别 1男 2女
HeadUrl string //头像Id
}
//测试 系统 直连模式
func Test_sys(t *testing.T) {
if err := mgo.OnInit(map[string]interface{}{
"MongodbUrl": "mongodb://127.0.0.1:37017",
"MongodbDatabase": "testdb",
}); err == nil {
if _, err := mgo.UpdateOne(Sql_UserDataTable,
bson.M{"_id": 10001},
bson.M{"$set": bson.M{
"nicename": "liwei1dao",
"headurl": "http://test.web.com",
"sex": 1,
}},
new(options.UpdateOptions).SetUpsert(true)); err != nil {
fmt.Printf("UpdateOne errr:%v", err)
}
data := &TestData{}
if err := mgo.FindOne(Sql_UserDataTable, bson.M{"_id": 10002}).Decode(data); err != nil {
fmt.Printf("FindOne errr:%v", err)
} else {
fmt.Printf("FindOne data:%+v", data)
}
} else {
fmt.Printf("OnInit errr:%v", err)
}
}
//测试 事务 副本集模式
func Test_Affair(t *testing.T) {
if err := mgo.OnInit(map[string]interface{}{
"MongodbUrl": "mongodb://root:123@127.0.0.1:37017,127.0.0.1:37018,127.0.0.1:37019/admin?replicaSet=mongoReplSet",
"MongodbDatabase": "testdb",
}); err == nil {
err = mgo.UseSession(func(sessionContext mongo.SessionContext) error {
err := sessionContext.StartTransaction()
if err != nil {
fmt.Println(err)
return err
}
col := mgo.Collection(Sql_UserDataTable)
//在事务内写一条id为“222”的记录
_, err = col.InsertOne(sessionContext, bson.M{"_id": 10004, "nicename": "liwei2dao", "headurl": "http://test1.web.com", "sex": 2})
if err != nil {
fmt.Println(err)
return err
}
//在事务内写一条id为“333”的记录
_, err = col.InsertOne(sessionContext, bson.M{"_id": 10005, "nicename": "liwei3dao", "headurl": "http://test1.web.com", "sex": 2})
if err != nil {
sessionContext.AbortTransaction(sessionContext)
return err
} else {
sessionContext.CommitTransaction(sessionContext)
}
return nil
})
fmt.Printf("FindOne errr:%v", err)
} else {
fmt.Printf("FindOne errr:%v", err)
}
}
//测试创建索引 过期索引
func Test_CreateTTLIndex(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("square"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
indexModel := mongo.IndexModel{
Keys: bsonx.Doc{{"expire_date", bsonx.Int32(1)}}, // 设置TTL索引列"expire_date"
Options: options.Index().SetExpireAfterSeconds(1 * 24 * 3600), // 设置过期时间1天条目过期一天过自动删除
}
str, err := sys.CreateIndex(core.SqlTable("dynamics"), indexModel)
if err != nil {
fmt.Printf("CreateIndex err:%v", err)
} else {
fmt.Printf("CreateIndex str:%v", str)
}
}
//测试创建索引 地图索引
func Test_CreateIndex(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("square"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
indexModel := mongo.IndexModel{
Keys: bson.M{"location": "2dsphere"},
Options: options.Index().SetBits(11111),
}
str, err := sys.CreateIndex(core.SqlTable("dynamics"), indexModel)
if err != nil {
fmt.Printf("CreateIndex err:%v", err)
} else {
fmt.Printf("CreateIndex str:%v", str)
}
}
//创建复合索引
func Test_CreateCompoundIndex(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("lego_yl"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
str, err := sys.CreateIndex(core.SqlTable("unreadmsg"), mongo.IndexModel{Keys: bson.M{"channeltype": 1, "targetid": 1, "uid": 1, "unreadmsg.sendtime": 1}}, nil)
if err != nil {
fmt.Printf("CreateIndex err:%v", err)
} else {
fmt.Printf("CreateIndex str:%v", str)
}
}
//测试删除索引 地图索引
func Test_DeleteIndex(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("square"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
_, err = sys.DeleteIndex(core.SqlTable("dynamics"), "location_2dsphere", nil)
if err != nil {
fmt.Printf("DeleteIndex err:%v", err)
} else {
fmt.Printf("DeleteIndex succ")
}
}
//测试附近查找
/*
db.<collection>.find( { <location field> :
{ $near :
{ $geometry :
{ type : "Point" ,coordinates : [ <longitude> , <latitude> ] } ,
$maxDistance : <distance in meters>
}
}
})
*/
func Test_QueryRound(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("square"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
filter := bson.M{
"location": bson.D{
{"$near", bson.D{
{"$geometry", bson.M{"type": "Point", "coordinates": []float64{113.867584, 22.56532}}},
{"$maxDistance", 10000},
}},
},
}
_, err = sys.Find(core.SqlTable("dynamics"), filter)
if err != nil {
fmt.Printf("CreateIndex err:%v", err)
} else {
fmt.Printf("CreateIndex succ")
}
return
}
//聚合查询演示
func Test_Aggregate(t *testing.T) {
sys, err := mgo.NewSys(mgo.SetMongodbUrl("mongodb://47.90.84.157:9094"), mgo.SetMongodbDatabase("square"))
if err != nil {
fmt.Printf("start sys Fail err:%v", err)
return
}
result := make([]bson.M, 0)
var cursor *mongo.Cursor
matchStage := bson.D{{"$match", bson.M{"_id": 979332}}}
unwindStage := bson.D{{"$unwind", "$chatmsg"}}
match2Stage := bson.D{{"$match", bson.M{"chatmsg.sendtime": bson.M{"$gt": 1611890940100, "$lt": 1611893135929}}}}
groupStage := bson.D{{"$group", bson.M{"_id": 979332, "chatmsg": bson.M{"$push": "$chatmsg"}}}}
projectStage := bson.D{{"$project", bson.M{"_id": 1, "chatmsg": 1}}}
if cursor, err = sys.Aggregate(core.SqlTable("grouprecorddata"), mongo.Pipeline{matchStage, unwindStage, match2Stage, groupStage, projectStage}); err == nil {
err = cursor.All(context.Background(), &result)
}
return
}

98
lego/sys/nacos/core.go Normal file
View File

@ -0,0 +1,98 @@
package nacos
import (
"github.com/nacos-group/nacos-sdk-go/model"
"github.com/nacos-group/nacos-sdk-go/vo"
)
type (
ISys interface {
Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error)
Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error)
Naming_GetService(param vo.GetServiceParam) (services model.Service, err error)
Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error)
Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error)
Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error)
Naming_Subscribe(param *vo.SubscribeParam) (err error)
Naming_Unsubscribe(param *vo.SubscribeParam) (err error)
Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error)
Config_GetConfig(param vo.ConfigParam) (string, error)
Config_PublishConfig(param vo.ConfigParam) (bool, error)
Config_DeleteConfig(param vo.ConfigParam) (bool, error)
Config_ListenConfig(params vo.ConfigParam) (err error)
Config_CancelListenConfig(params vo.ConfigParam) (err error)
Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error)
Config_PublishAggr(param vo.ConfigParam) (published bool, err error)
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
///注册服务
func Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error) {
return defsys.Naming_RegisterInstance(service)
}
///注销服务
func Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error) {
return defsys.Naming_DeregisterInstance(service)
}
///获取服务
func Naming_GetService(param vo.GetServiceParam) (services model.Service, err error) {
return defsys.Naming_GetService(param)
}
///获取全部服务实例
func Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error) {
return defsys.Naming_SelectAllInstances(param)
}
func Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error) {
return defsys.Naming_SelectInstances(param)
}
func Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error) {
return defsys.Naming_SelectOneHealthyInstance(param)
}
func Naming_Subscribe(param *vo.SubscribeParam) (err error) {
return defsys.Naming_Subscribe(param)
}
func Naming_Unsubscribe(param *vo.SubscribeParam) (err error) {
return defsys.Naming_Unsubscribe(param)
}
func Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error) {
return defsys.Naming_GetAllServicesInfo(param)
}
func Config_GetConfig(param vo.ConfigParam) (string, error) {
return defsys.Config_GetConfig(param)
}
func Config_PublishConfig(param vo.ConfigParam) (bool, error) {
return defsys.Config_PublishConfig(param)
}
func Config_DeleteConfig(param vo.ConfigParam) (bool, error) {
return defsys.Config_DeleteConfig(param)
}
func Config_ListenConfig(params vo.ConfigParam) (err error) {
return defsys.Config_ListenConfig(params)
}
func Config_CancelListenConfig(params vo.ConfigParam) (err error) {
return defsys.Config_ListenConfig(params)
}
func Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error) {
return defsys.Config_SearchConfig(param)
}
func Config_PublishAggr(param vo.ConfigParam) (published bool, err error) {
return defsys.Config_PublishAggr(param)
}

143
lego/sys/nacos/nacos.go Normal file
View File

@ -0,0 +1,143 @@
package nacos
import (
"github.com/nacos-group/nacos-sdk-go/clients"
"github.com/nacos-group/nacos-sdk-go/clients/config_client"
"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
"github.com/nacos-group/nacos-sdk-go/common/constant"
"github.com/nacos-group/nacos-sdk-go/model"
"github.com/nacos-group/nacos-sdk-go/vo"
)
func newSys(options Options) (sys *Nacos, err error) {
sys = &Nacos{
options: options,
}
// 创建clientConfig
clientConfig := constant.ClientConfig{
NamespaceId: options.NamespaceId,
TimeoutMs: options.TimeoutMs,
NotLoadCacheAtStart: true,
Username: options.Username,
Password: options.Password,
LogDir: "./nacos/log",
CacheDir: "./nacos/cache",
RotateTime: "1h",
MaxAge: 3,
LogLevel: "debug",
}
// 至少一个ServerConfig
serverConfigs := []constant.ServerConfig{
{
IpAddr: options.NacosAddr,
ContextPath: "/nacos",
Port: options.Port,
Scheme: "http",
},
}
if sys.options.NacosClientType == NamingClient || sys.options.NacosClientType == All {
// 创建服务发现客户端的另一种方式 (推荐)
sys.namingClient, err = clients.NewNamingClient(
vo.NacosClientParam{
ClientConfig: &clientConfig,
ServerConfigs: serverConfigs,
},
)
}
if sys.options.NacosClientType == ConfigClient || sys.options.NacosClientType == All {
// 创建服务发现客户端的另一种方式 (推荐)
sys.configClient, err = clients.NewConfigClient(
vo.NacosClientParam{
ClientConfig: &clientConfig,
ServerConfigs: serverConfigs,
},
)
}
return
}
type Nacos struct {
options Options
namingClient naming_client.INamingClient
configClient config_client.IConfigClient
}
///注册服务
func (this *Nacos) Naming_RegisterInstance(service vo.RegisterInstanceParam) (success bool, err error) {
success, err = this.namingClient.RegisterInstance(service)
return
}
///注销服务
func (this *Nacos) Naming_DeregisterInstance(service vo.DeregisterInstanceParam) (success bool, err error) {
success, err = this.namingClient.DeregisterInstance(service)
return
}
///获取服务
func (this *Nacos) Naming_GetService(param vo.GetServiceParam) (services model.Service, err error) {
services, err = this.namingClient.GetService(param)
return
}
/// SelectAllInstance可以返回全部实例列表,包括healthy=false,enable=false,weight<=0
func (this *Nacos) Naming_SelectAllInstances(param vo.SelectAllInstancesParam) (instances []model.Instance, err error) {
instances, err = this.namingClient.SelectAllInstances(param)
return
}
///选中实例列表
func (this *Nacos) Naming_SelectInstances(param vo.SelectInstancesParam) (instances []model.Instance, err error) {
instances, err = this.namingClient.SelectInstances(param)
return
}
/// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例 实例必须满足的条件health=true,enable=true and weight>0
func (this *Nacos) Naming_SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (instance *model.Instance, err error) {
instance, err = this.namingClient.SelectOneHealthyInstance(param)
return
}
/// Subscribe key=serviceName+groupName+cluster 注意:我们可以在相同的key添加多个SubscribeCallback.
func (this *Nacos) Naming_Subscribe(param *vo.SubscribeParam) (err error) {
err = this.namingClient.Subscribe(param)
return
}
func (this *Nacos) Naming_Unsubscribe(param *vo.SubscribeParam) (err error) {
err = this.namingClient.Unsubscribe(param)
return
}
func (this *Nacos) Naming_GetAllServicesInfo(param vo.GetAllServiceInfoParam) (serviceInfos model.ServiceList, err error) {
serviceInfos, err = this.namingClient.GetAllServicesInfo(param)
return
}
func (this *Nacos) Config_GetConfig(param vo.ConfigParam) (string, error) {
return this.configClient.GetConfig(param)
}
func (this *Nacos) Config_PublishConfig(param vo.ConfigParam) (bool, error) {
return this.configClient.PublishConfig(param)
}
func (this *Nacos) Config_DeleteConfig(param vo.ConfigParam) (bool, error) {
return this.configClient.PublishConfig(param)
}
func (this *Nacos) Config_ListenConfig(params vo.ConfigParam) (err error) {
return this.configClient.ListenConfig(params)
}
func (this *Nacos) Config_CancelListenConfig(params vo.ConfigParam) (err error) {
return this.configClient.CancelListenConfig(params)
}
func (this *Nacos) Config_SearchConfig(param vo.SearchConfigParam) (*model.ConfigPage, error) {
return this.configClient.SearchConfig(param)
}
func (this *Nacos) Config_PublishAggr(param vo.ConfigParam) (published bool, err error) {
return this.configClient.PublishAggr(param)
}

86
lego/sys/nacos/options.go Normal file
View File

@ -0,0 +1,86 @@
package nacos
import (
"go_dreamfactory/lego/utils/mapstructure"
)
type NacosClientType uint8
const (
NamingClient NacosClientType = iota
ConfigClient
All
)
type Option func(*Options)
type Options struct {
NacosClientType NacosClientType
NamespaceId string
NacosAddr string
Port uint64
Username string
Password string
TimeoutMs uint64
}
func SetNacosClientType(v NacosClientType) Option {
return func(o *Options) {
o.NacosClientType = v
}
}
func SetNamespaceId(v string) Option {
return func(o *Options) {
o.NamespaceId = v
}
}
func SetNacosAddr(v string) Option {
return func(o *Options) {
o.NacosAddr = v
}
}
func SetPort(v uint64) Option {
return func(o *Options) {
o.Port = v
}
}
func SetUsername(v string) Option {
return func(o *Options) {
o.Username = v
}
}
func SetPassword(v string) Option {
return func(o *Options) {
o.Password = v
}
}
func SetTimeoutMs(v uint64) Option {
return func(o *Options) {
o.TimeoutMs = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
TimeoutMs: 5000,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
TimeoutMs: 5000,
}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,43 @@
package nacos_test
import (
"fmt"
"testing"
"go_dreamfactory/lego/sys/nacos"
"github.com/nacos-group/nacos-sdk-go/vo"
)
func Test_SysInit(t *testing.T) {
sys, err := nacos.NewSys(
nacos.SetNacosAddr("127.0.0.1"),
nacos.SetPort(8848),
nacos.SetNamespaceId("17d02ef9-afaa-4878-ad6c-9fd697f3b628"),
)
if err != nil {
fmt.Printf("启动系统错误err:%v", err)
}
succ, err := sys.Naming_RegisterInstance(vo.RegisterInstanceParam{
Ip: "127.0.0.1",
Port: 8848,
Weight: 0.69,
GroupName: "demo",
ClusterName: "demo",
ServiceName: "demo1",
Metadata: map[string]string{
"tag": "demo",
},
})
fmt.Printf("sys RegisterInstance succ:%v err:%v", succ, err)
// time.Sleep(time.Second * 3)
serviceInfos, err := sys.Naming_GetAllServicesInfo(vo.GetAllServiceInfoParam{
NameSpace: "17d02ef9-afaa-4878-ad6c-9fd697f3b628",
GroupName: "demo",
})
fmt.Printf("sys GetAllServicesInfo serviceInfos:%+v err:%v", serviceInfos, err)
// succ, err = sys.DeregisterInstance()
// fmt.Printf("sys DeregisterInstance succ:%v err:%v", succ, err)
}

63
lego/sys/proto/core.go Normal file
View File

@ -0,0 +1,63 @@
package proto
import (
"bufio"
"reflect"
)
type (
IMessage interface {
GetComId() uint16
GetMsgId() uint16
GetMsgLen() uint32
GetBuffer() []byte
ToStriing() string
}
IMessageFactory interface {
SetMessageConfig(MsgProtoType ProtoType, IsUseBigEndian bool)
DecodeMessageBybufio(r *bufio.Reader) (message IMessage, err error)
DecodeMessageBybytes(buffer []byte) (message IMessage, err error)
EncodeToMesage(comId uint16, msgId uint16, msg interface{}) (message IMessage)
EncodeToByte(message IMessage) (buffer []byte)
RpcEncodeMessage(d interface{}) ([]byte, error)
RpcDecodeMessage(dataType reflect.Type, d []byte) (interface{}, error)
}
ISys interface {
DecodeMessageBybufio(r *bufio.Reader) (message IMessage, err error)
DecodeMessageBybytes(buffer []byte) (message IMessage, err error)
EncodeToMesage(comId uint16, msgId uint16, msg interface{}) (message IMessage)
EncodeToByte(message IMessage) (buffer []byte)
ByteDecodeToStruct(t reflect.Type, d []byte) (interface{}, error)
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func DecodeMessageBybufio(r *bufio.Reader) (IMessage, error) {
return defsys.DecodeMessageBybufio(r)
}
func DecodeMessageBybytes(buffer []byte) (msg IMessage, err error) {
return defsys.DecodeMessageBybytes(buffer)
}
func EncodeToMesage(comId uint16, msgId uint16, msg interface{}) (message IMessage) {
return defsys.EncodeToMesage(comId, msgId, msg)
}
func EncodeToByte(message IMessage) (buffer []byte) {
return defsys.EncodeToByte(message)
}
func ByteDecodeToStruct(t reflect.Type, d []byte) (interface{}, error) {
return defsys.ByteDecodeToStruct(t, d)
}

View File

@ -0,0 +1,218 @@
package proto
import (
"bufio"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"reflect"
"go_dreamfactory/lego/sys/rpc"
"github.com/golang/protobuf/proto"
)
//默认消息体
type DefMessage struct {
ComId uint16 //主Id
MsgId uint16 //次Id
MsgLen uint32 //消息体长度
Buffer []byte //消息体
}
func (this *DefMessage) GetComId() uint16 {
return this.ComId
}
func (this *DefMessage) GetMsgId() uint16 {
return this.MsgId
}
func (this *DefMessage) GetMsgLen() uint32 {
return this.MsgLen
}
func (this *DefMessage) GetBuffer() []byte {
return this.Buffer
}
func (this *DefMessage) ToStriing() string {
return fmt.Sprintf("ComId%d MsgId:%d MsgLen:%d", this.ComId, this.MsgId, this.MsgLen)
}
//默认消息工厂
type DefMessageFactory struct {
msgProtoType ProtoType //消息体类型
isUseBigEndian bool //消息传输码
msgheadsize uint32 //消息头大小
msgmaxleng uint32 //消息体最大长度
}
func (this *DefMessageFactory) SetMessageConfig(MsgProtoType ProtoType, IsUseBigEndian bool) {
this.msgProtoType = MsgProtoType
this.isUseBigEndian = IsUseBigEndian
this.msgheadsize = 8
this.msgmaxleng = 1024 * 1204 * 3
//自己rpc消息解析
rpc.OnRegisterRpcData(&DefMessage{}, this.RpcEncodeMessage, this.RpcDecodeMessage)
}
func (this *DefMessageFactory) DecodeMessageBybufio(r *bufio.Reader) (message IMessage, err error) {
msg := &DefMessage{}
msg.ComId, err = this.readUInt16(r)
if err != nil {
return msg, err
}
msg.MsgId, err = this.readUInt16(r)
if err != nil {
return msg, err
}
msg.MsgLen, err = this.readUInt32(r)
if err != nil {
return msg, err
}
if msg.MsgLen > this.msgmaxleng {
return nil, fmt.Errorf("DecodeMessageBybufio err msg.MsgLen:%d Super long", msg.MsgLen)
}
msg.Buffer = make([]byte, msg.MsgLen)
_, err = io.ReadFull(r, msg.Buffer)
return msg, err
}
func (this *DefMessageFactory) DecodeMessageBybytes(buffer []byte) (message IMessage, err error) {
if uint32(len(buffer)) >= this.msgheadsize {
msg := &DefMessage{}
if this.isUseBigEndian {
msg.ComId = binary.BigEndian.Uint16(buffer[0:])
msg.MsgId = binary.BigEndian.Uint16(buffer[2:])
msg.MsgLen = binary.BigEndian.Uint32(buffer[4:])
} else {
msg.ComId = binary.LittleEndian.Uint16(buffer[0:])
msg.MsgId = binary.LittleEndian.Uint16(buffer[2:])
msg.MsgLen = binary.LittleEndian.Uint32(buffer[4:])
}
if uint32(len(buffer)) >= msg.MsgLen+this.msgheadsize {
msg.Buffer = buffer[this.msgheadsize : msg.MsgLen+this.msgheadsize]
return msg, nil
} else {
return nil, fmt.Errorf("DecodeMessageBybytes err package:%v msg.MsgLen:%d", buffer, msg.MsgLen)
}
}
return nil, fmt.Errorf("DecodeMessageBybytes err package:%v", buffer)
}
func (this *DefMessageFactory) EncodeToMesage(comId uint16, msgId uint16, msg interface{}) (message IMessage) {
defmessage := &DefMessage{
ComId: uint16(comId),
MsgId: uint16(msgId),
}
if this.msgProtoType == Proto_Buff {
defmessage.Buffer, _ = proto.Marshal(msg.(proto.Message))
} else {
defmessage.Buffer, _ = json.Marshal(msg)
}
defmessage.MsgLen = uint32(len(defmessage.Buffer))
return defmessage
}
func (this *DefMessageFactory) EncodeToByte(message IMessage) (buffer []byte) {
if this.isUseBigEndian {
buffer := []byte{}
_msg := make([]byte, 2)
binary.BigEndian.PutUint16(_msg, message.GetComId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 2)
binary.BigEndian.PutUint16(_msg, message.GetMsgId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 4)
binary.BigEndian.PutUint32(_msg, message.GetMsgLen())
buffer = append(buffer, _msg...)
buffer = append(buffer, message.GetBuffer()...)
return buffer
} else {
buffer := []byte{}
_msg := make([]byte, 2)
binary.LittleEndian.PutUint16(_msg, message.GetComId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 2)
binary.LittleEndian.PutUint16(_msg, message.GetMsgId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 4)
binary.LittleEndian.PutUint32(_msg, message.GetMsgLen())
buffer = append(buffer, _msg...)
buffer = append(buffer, message.GetBuffer()...)
return buffer
}
}
func (this *DefMessageFactory) RpcEncodeMessage(d interface{}) ([]byte, error) {
message := d.(IMessage)
if this.isUseBigEndian {
buffer := []byte{}
_msg := make([]byte, 2)
binary.BigEndian.PutUint16(_msg, message.GetComId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 2)
binary.BigEndian.PutUint16(_msg, message.GetMsgId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 4)
binary.BigEndian.PutUint32(_msg, message.GetMsgLen())
buffer = append(buffer, _msg...)
buffer = append(buffer, message.GetBuffer()...)
return buffer, nil
} else {
buffer := []byte{}
_msg := make([]byte, 2)
binary.LittleEndian.PutUint16(_msg, message.GetComId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 2)
binary.LittleEndian.PutUint16(_msg, message.GetMsgId())
buffer = append(buffer, _msg...)
_msg = make([]byte, 4)
binary.LittleEndian.PutUint32(_msg, message.GetMsgLen())
buffer = append(buffer, _msg...)
buffer = append(buffer, message.GetBuffer()...)
return buffer, nil
}
}
func (this *DefMessageFactory) RpcDecodeMessage(dataType reflect.Type, d []byte) (interface{}, error) {
return this.DecodeMessageBybytes(d)
}
func (this *DefMessageFactory) readByte(r *bufio.Reader) (byte, error) {
buf := make([]byte, 1)
_, err := io.ReadFull(r, buf[:1])
if err != nil {
return 0, err
}
return buf[0], nil
}
func (this *DefMessageFactory) readUInt16(r *bufio.Reader) (uint16, error) {
buf := make([]byte, 2)
_, err := io.ReadFull(r, buf[:2])
if err != nil {
return 0, err
}
if this.isUseBigEndian {
return binary.BigEndian.Uint16(buf[:2]), nil
} else {
return binary.LittleEndian.Uint16(buf[:2]), nil
}
}
func (this *DefMessageFactory) readUInt32(r *bufio.Reader) (uint32, error) {
buf := make([]byte, 4)
_, err := io.ReadFull(r, buf[:4])
if err != nil {
return 0, err
}
if this.isUseBigEndian {
return binary.BigEndian.Uint32(buf[:4]), nil
} else {
return binary.LittleEndian.Uint32(buf[:4]), nil
}
}

68
lego/sys/proto/options.go Normal file
View File

@ -0,0 +1,68 @@
package proto
import (
"go_dreamfactory/lego/utils/mapstructure"
)
type ProtoType uint8
const (
Proto_Json ProtoType = 1
Proto_Buff ProtoType = 2
)
type Option func(*Options)
type Options struct {
MsgProtoType ProtoType
IsUseBigEndian bool
MessageFactory IMessageFactory
}
func SetMsgProtoType(v ProtoType) Option {
return func(o *Options) {
o.MsgProtoType = v
}
}
func SetIsUseBigEndian(v bool) Option {
return func(o *Options) {
o.IsUseBigEndian = v
}
}
func SetMessageFactory(v IMessageFactory) Option {
return func(o *Options) {
o.MessageFactory = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
MsgProtoType: Proto_Buff,
IsUseBigEndian: false,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
if options.MessageFactory == nil {
options.MessageFactory = new(DefMessageFactory)
}
return options
}
func newOptionsByOption(opts ...Option) Options {
options := Options{
MsgProtoType: Proto_Buff,
IsUseBigEndian: false,
}
for _, o := range opts {
o(&options)
}
if options.MessageFactory == nil {
options.MessageFactory = new(DefMessageFactory)
}
return options
}

48
lego/sys/proto/proto.go Normal file
View File

@ -0,0 +1,48 @@
package proto
import (
"bufio"
"encoding/json"
"reflect"
"github.com/golang/protobuf/proto"
)
func newSys(options Options) (sys *Proto, err error) {
sys = &Proto{
options: options,
}
options.MessageFactory.SetMessageConfig(options.MsgProtoType, options.IsUseBigEndian)
return
}
type Proto struct {
options Options
}
func (this *Proto) DecodeMessageBybufio(r *bufio.Reader) (message IMessage, err error) {
return this.options.MessageFactory.DecodeMessageBybufio(r)
}
func (this *Proto) DecodeMessageBybytes(buffer []byte) (message IMessage, err error) {
return this.options.MessageFactory.DecodeMessageBybytes(buffer)
}
func (this *Proto) EncodeToMesage(comId uint16, msgId uint16, msg interface{}) (message IMessage) {
return this.options.MessageFactory.EncodeToMesage(comId, msgId, msg)
}
func (this *Proto) EncodeToByte(message IMessage) (buffer []byte) {
return this.options.MessageFactory.EncodeToByte(message)
}
func (this *Proto) ByteDecodeToStruct(t reflect.Type, d []byte) (data interface{}, err error) {
if this.options.MsgProtoType == Proto_Json {
data = reflect.New(t.Elem()).Interface()
err = json.Unmarshal(d, data)
} else {
data = reflect.New(t.Elem()).Interface()
err = proto.UnmarshalMerge(d, data.(proto.Message))
}
return
}

View File

@ -0,0 +1,93 @@
package cluster
import (
"context"
"time"
"github.com/go-redis/redis/v8"
)
func NewSys(RedisUrl []string, RedisPassword string, timeOut time.Duration,
encode func(value interface{}) (result []byte, err error),
decode func(value []byte, result interface{}) (err error),
) (sys *Redis, err error) {
var (
client *redis.ClusterClient
)
client = redis.NewClusterClient(&redis.ClusterOptions{
Addrs: RedisUrl,
Password: RedisPassword,
})
sys = &Redis{
client: client,
timeOut: timeOut,
Encode: encode,
Decode: decode,
}
_, err = sys.Ping()
return
}
type Redis struct {
client *redis.ClusterClient
timeOut time.Duration
Encode func(value interface{}) (result []byte, err error)
Decode func(value []byte, result interface{}) (err error)
}
func (this *Redis) getContext() (ctx context.Context) {
ctx, _ = context.WithTimeout(context.Background(), this.timeOut)
return
}
///事务
func (this *Redis) Close() (err error) {
err = this.client.Close()
return
}
/// Ping
func (this *Redis) Ping() (string, error) {
return this.client.Ping(this.getContext()).Result()
}
/// 命令接口
func (this *Redis) Do(ctx context.Context, args ...interface{}) *redis.Cmd {
return this.client.Do(ctx, args...)
}
///批处理
func (this *Redis) Pipeline(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) {
_, err = this.client.Pipelined(ctx, fn)
return
}
///事务
func (this *Redis) TxPipelined(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) {
_, err = this.client.TxPipelined(ctx, fn)
return
}
///监控
func (this *Redis) Watch(ctx context.Context, fn func(*redis.Tx) error, keys ...string) (err error) {
agrs := make([]string, len(keys))
for i, v := range keys {
agrs[i] = string(v)
}
err = this.client.Watch(ctx, fn, agrs...)
return
}
//锁
func (this *Redis) Lock(key string, outTime int) (result bool, err error) {
cmd := redis.NewBoolCmd(this.getContext(), "set", key, 1, "ex", outTime, "nx")
this.client.Process(this.getContext(), cmd)
result, err = cmd.Result()
return
}
//锁
func (this *Redis) UnLock(key string) (err error) {
err = this.Delete(key)
return
}

View File

@ -0,0 +1,170 @@
package cluster
import (
"reflect"
"github.com/go-redis/redis/v8"
)
/*
Redis Hdel 命令用于删除哈希表 key 中的一个或多个指定字段不存在的字段将被忽略
*/
func (this *Redis) HDel(key string, fields ...string) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "HDEL")
agrs = append(agrs, key)
for _, v := range fields {
agrs = append(agrs, v)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Hexists 命令用于查看哈希表的指定字段是否存在
*/
func (this *Redis) HExists(key string, field string) (result bool, err error) {
result, err = this.client.Do(this.getContext(), "HEXISTS", key, field).Bool()
return
}
/*
Redis Hget 命令用于返回哈希表中指定字段的值
*/
func (this *Redis) HGet(key string, field string, value interface{}) (err error) {
var resultvalue string
if resultvalue = this.client.Do(this.getContext(), "HSET", key, field).String(); resultvalue != string(redis.Nil) {
err = this.Decode([]byte(resultvalue), value)
}
return
}
/*
Redis Hgetall 命令用于返回哈希表中所有的字段和值
在返回值里紧跟每个字段名(field name)之后是字段的值(value)所以返回值的长度是哈希表大小的两倍
*/
func (this *Redis) HGetAll(key string, valuetype reflect.Type) (result []interface{}, err error) {
cmd := redis.NewStringSliceCmd(this.getContext(), "HGETALL", key)
this.client.Process(this.getContext(), cmd)
var _result []string
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Hincrby 命令用于为哈希表中的字段值加上指定增量值
增量也可以为负数相当于对指定字段进行减法操作
如果哈希表的 key 不存在一个新的哈希表被创建并执行 HINCRBY 命令
如果指定的字段不存在那么在执行命令前字段的值被初始化为 0
对一个储存字符串值的字段执行 HINCRBY 命令将造成一个错误
本操作的值被限制在 64 (bit)有符号数字表示之内
*/
func (this *Redis) HIncrBy(key string, field string, value int) (err error) {
err = this.client.Do(this.getContext(), "HINCRBY", key, field, value).Err()
return
}
/*
Redis Hincrbyfloat 命令用于为哈希表中的字段值加上指定浮点数增量值
如果指定的字段不存在那么在执行命令前字段的值被初始化为 0
*/
func (this *Redis) HIncrByFloat(key string, field string, value float32) (err error) {
err = this.client.Do(this.getContext(), "HINCRBYFLOAT", key, field, value).Err()
return
}
/*
Redis Hkeys 命令用于获取哈希表中的所有域(field)
*/
func (this *Redis) Hkeys(key string) (result []string, err error) {
cmd := redis.NewStringSliceCmd(this.getContext(), "HKEYS", key)
this.client.Process(this.getContext(), cmd)
result, err = cmd.Result()
return
}
/*
Redis Hlen 命令用于获取哈希表中字段的数量
*/
func (this *Redis) Hlen(key string) (result int, err error) {
result, err = this.client.Do(this.getContext(), "HLEN", key).Int()
return
}
/*
Redis Hmget 命令用于返回哈希表中一个或多个给定字段的值
如果指定的字段不存在于哈希表那么返回一个 nil
*/
func (this *Redis) HMGet(key string, valuetype reflect.Type, fields ...string) (result []interface{}, err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "HMGET")
agrs = append(agrs, key)
for _, v := range fields {
agrs = append(agrs, v)
}
cmd := redis.NewStringSliceCmd(this.getContext(), agrs...)
this.client.Process(this.getContext(), cmd)
var _result []string
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Hmset 命令用于同时将多个 field-value (字段-)对设置到哈希表中
此命令会覆盖哈希表中已存在的字段
如果哈希表不存在会创建一个空哈希表并执行 HMSET 操作
*/
func (this *Redis) HMSet(key string, value map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "HMSET")
agrs = append(agrs, key)
for k, v := range value {
result, _ := this.Encode(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Hset 命令用于为哈希表中的字段赋值
如果哈希表不存在一个新的哈希表被创建并进行 HSET 操作
如果字段已经存在于哈希表中旧值将被覆盖
*/
func (this *Redis) HSet(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.Encode(value); err == nil {
err = this.client.Do(this.getContext(), "HSET", key, field, resultvalue).Err()
}
return
}
/*
Redis Hsetnx 命令用于为哈希表中不存在的的字段赋值
如果哈希表不存在一个新的哈希表被创建并进行 HSET 操作
如果字段已经存在于哈希表中操作无效
如果 key 不存在一个新哈希表被创建并执行 HSETNX 命令
*/
func (this *Redis) HSetNX(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.Encode(value); err == nil {
err = this.client.Do(this.getContext(), "HSETNX", key, field, resultvalue).Err()
}
return
}

View File

@ -0,0 +1,88 @@
package cluster
import (
"github.com/go-redis/redis/v8"
)
/* Key *******************************************************************************/
///删除redis key
func (this *Redis) Delete(key string) (err error) {
err = this.client.Do(this.getContext(), "DEL", key).Err()
return
}
///判断是否存在key
func (this *Redis) ExistsKey(key string) (iskeep bool, err error) {
iskeep, err = this.client.Do(this.getContext(), "EXISTS", key).Bool()
return
}
///设置key的过期时间 单位以秒级
func (this *Redis) ExpireKey(key string, expire int) (err error) {
err = this.client.Do(this.getContext(), "EXPIRE", key, expire).Err()
return
}
///设置key的过期时间戳 秒级时间戳
func (this *Redis) ExpireatKey(key string, expire_unix int64) (err error) {
err = this.client.Do(this.getContext(), "EXPIREAT", key, expire_unix).Err()
return
}
///设置key的过期时间 单位以毫秒级
func (this *Redis) Pexpirekey(key string, expire int) (err error) {
err = this.client.Do(this.getContext(), "PEXPIRE", key, expire).Err()
return
}
///设置key的过期时间戳 单位以豪秒级
func (this *Redis) PexpireatKey(key string, expire_unix int64) (err error) {
err = this.client.Do(this.getContext(), "PEXPIREAT", key, expire_unix).Err()
return
}
///移除Key的过期时间
func (this *Redis) PersistKey(key string) (err error) {
err = this.client.Do(this.getContext(), "PERSIST", key).Err()
return
}
///获取key剩余过期时间 单位毫秒
func (this *Redis) PttlKey(key string) (leftexpire int64, err error) {
leftexpire, err = this.client.Do(this.getContext(), "PTTL", key).Int64()
return
}
///获取key剩余过期时间 单位秒
func (this *Redis) TtlKey(key string) (leftexpire int64, err error) {
leftexpire, err = this.client.Do(this.getContext(), "TTL", key).Int64()
return
}
///重命名Key
func (this *Redis) RenameKye(oldkey string, newkey string) (err error) {
err = this.client.Do(this.getContext(), "RENAME", oldkey, newkey).Err()
return
}
///重命名key 在新的 key 不存在时修改 key 的名称
func (this *Redis) RenamenxKey(oldkey string, newkey string) (err error) {
err = this.client.Do(this.getContext(), "RENAMENX", oldkey, newkey).Err()
return
}
///判断是否存在key pattern:key*
func (this *Redis) Keys(pattern string) (keys []string, err error) {
cmd := redis.NewStringSliceCmd(this.getContext(), "KEYS", string(pattern))
this.client.Process(this.getContext(), cmd)
keys, err = cmd.Result()
return
}
///获取键类型
func (this *Redis) Type(key string) (ty string, err error) {
ty, err = this.client.Type(this.getContext(), key).Result()
return
}

View File

@ -0,0 +1,205 @@
package cluster
import (
"fmt"
"reflect"
"github.com/go-redis/redis/v8"
)
/*
Redis Lindex 命令用于通过索引获取列表中的元素你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
*/
func (this *Redis) Lindex(key string, value interface{}) (err error) {
var data string
if data = this.client.Do(this.getContext(), "LINDEX", key).String(); data != string(redis.Nil) {
err = this.Decode([]byte(data), value)
} else {
err = fmt.Errorf(string(redis.Nil))
}
return
}
/*
Redis Linsert 命令用于在列表的元素前或者后插入元素当指定元素不存在于列表中时不执行任何操作
当列表不存在时被视为空列表不执行任何操作
如果 key 不是列表类型返回一个错误
*/
func (this *Redis) Linsert(key string, isbefore bool, tager interface{}, value interface{}) (err error) {
var (
tagervalue []byte
resultvalue []byte
)
if tagervalue, err = this.Encode(tager); err == nil {
if resultvalue, err = this.Encode(value); err == nil {
if isbefore {
err = this.client.Do(this.getContext(), "LINSERT", key, "BEFORE", tagervalue, resultvalue).Err()
} else {
err = this.client.Do(this.getContext(), "LINSERT", key, "AFTER", tagervalue, resultvalue).Err()
}
}
}
return
}
/*
Redis Llen 命令用于返回列表的长度 如果列表 key 不存在 key 被解释为一个空列表返回 0 如果 key 不是列表类型返回一个错误
*/
func (this *Redis) Llen(key string) (result int, err error) {
result, err = this.client.Do(this.getContext(), "LLEN", key).Int()
return
}
/*
Redis Lpop 命令用于移除并返回列表的第一个元素
*/
func (this *Redis) LPop(key string, value interface{}) (err error) {
var data string
if data = this.client.Do(this.getContext(), "LPOP", key).String(); data != string(redis.Nil) {
err = this.Decode([]byte(data), value)
} else {
err = fmt.Errorf(string(redis.Nil))
}
return
}
/*
Redis Lpush 命令将一个或多个值插入到列表头部 如果 key 不存在一个空列表会被创建并执行 LPUSH 操作 key 存在但不是列表类型时返回一个错误
*/
func (this *Redis) LPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSH")
for _, v := range values {
result, _ := this.Encode(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Lpushx 将一个值插入到已存在的列表头部列表不存在时操作无效
*/
func (this *Redis) LPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSHX")
for _, v := range values {
result, _ := this.Encode(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Lrange 返回列表中指定区间内的元素区间以偏移量 START END 指定 其中 0 表示列表的第一个元素 1 表示列表的第二个元素
以此类推 你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
*/
func (this *Redis) LRange(key string, start, end int, valuetype reflect.Type) (result []interface{}, err error) {
var _result []string
cmd := redis.NewStringSliceCmd(this.getContext(), "LRANGE", key, start, end)
this.client.Process(this.getContext(), cmd)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Lrem 根据参数 COUNT 的值移除列表中与参数 VALUE 相等的元素
COUNT 的值可以是以下几种
count > 0 : 从表头开始向表尾搜索移除与 VALUE 相等的元素数量为 COUNT
count < 0 : 从表尾开始向表头搜索移除与 VALUE 相等的元素数量为 COUNT 的绝对值
count = 0 : 移除表中所有与 VALUE 相等的值
*/
func (this *Redis) LRem(key string, count int, target interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.Encode(target); err == nil {
err = this.client.Do(this.getContext(), "LREM", key, count, resultvalue).Err()
}
return
}
/*
Redis Lset 通过索引来设置元素的值
当索引参数超出范围或对一个空列表进行 LSET 返回一个错误
*/
func (this *Redis) LSet(key string, index int, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.Encode(value); err == nil {
err = this.client.Do(this.getContext(), "LSET", key, index, resultvalue).Err()
}
return
}
/*
Redis Ltrim 对一个列表进行修剪(trim)就是说让列表只保留指定区间内的元素不在指定区间之内的元素都将被删除
下标 0 表示列表的第一个元素 1 表示列表的第二个元素以此类推 你也可以使用负数下标
-1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
*/
func (this *Redis) Ltrim(key string, start, stop int) (err error) {
err = this.client.Do(this.getContext(), "LTRIM", key, start, stop).Err()
return
}
/*
Redis Rpop 命令用于移除列表的最后一个元素返回值为移除的元素
*/
func (this *Redis) Rpop(key string, value interface{}) (err error) {
var data string
if data = this.client.Do(this.getContext(), "RPOP", key).String(); data != string(redis.Nil) {
err = this.Decode([]byte(data), value)
} else {
err = fmt.Errorf(string(redis.Nil))
}
return
}
/*
Redis Rpoplpush 命令用于移除列表的最后一个元素并将该元素添加到另一个列表并返回
*/
func (this *Redis) RPopLPush(oldkey string, newkey string, value interface{}) (err error) {
var data string
if data = this.client.Do(this.getContext(), "RPOPLPUSH", oldkey, newkey).String(); data != string(redis.Nil) {
err = this.Decode([]byte(data), value)
} else {
err = fmt.Errorf(string(redis.Nil))
}
return
}
/*
Redis Rpush 命令用于将一个或多个值插入到列表的尾部(最右边)
如果列表不存在一个空列表会被创建并执行 RPUSH 操作 当列表存在但不是列表类型时返回一个错误
注意 Redis 2.4 版本以前的 RPUSH 命令都只接受单个 value
*/
func (this *Redis) RPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSH")
for _, v := range values {
result, _ := this.Encode(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Rpushx 命令用于将一个值插入到已存在的列表尾部(最右边)如果列表不存在操作无效
*/
func (this *Redis) RPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSHX")
for _, v := range values {
result, _ := this.Encode(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}

View File

@ -0,0 +1,185 @@
package cluster
import "reflect"
/*
Redis Sadd 命令将一个或多个成员元素加入到集合中已经存在于集合的成员元素将被忽略
假如集合 key 不存在则创建一个只包含添加的元素作成员的集合
当集合 key 不是集合类型时返回一个错误
*/
func (this *Redis) SAdd(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "SADD")
agrs = append(agrs, key)
for _, v := range values {
result, _ := this.Encode(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Scard 命令返回集合中元素的数量
*/
func (this *Redis) SCard(key string) (result int64, err error) {
result, err = this.client.SCard(this.getContext(), key).Result()
return
}
/*
Redis Sdiff 命令返回第一个集合与其他集合之间的差异也可以认为说第一个集合中独有的元素不存在的集合 key 将视为空集
差集的结果来自前面的 FIRST_KEY ,而不是后面的 OTHER_KEY1也不是整个 FIRST_KEY OTHER_KEY1..OTHER_KEYN 的差集
实例:
*/
func (this *Redis) SDiff(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
var _result []string
cmd := this.client.SDiff(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Sdiffstore 命令将给定集合之间的差集合存储在指定的集合中
*/
func (this *Redis) SDiffStore(destination string, keys ...string) (result int64, err error) {
result, err = this.client.SDiffStore(this.getContext(), destination, keys...).Result()
return
}
/*
Redis Sismember 命令返回给定所有给定集合的交集 不存在的集合 key 被视为空集 当给定集合当中有一个空集时结果也为空集(根据集合运算定律)
*/
func (this *Redis) SInter(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
var _result []string
cmd := this.client.SInter(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Sinterstore 决定将给定集合之间的交集在指定的集合中如果指定的集合已经存在则将其覆盖
*/
func (this *Redis) SInterStore(destination string, keys ...string) (result int64, err error) {
result, err = this.client.SInterStore(this.getContext(), destination, keys...).Result()
return
}
/*
Redis Sismember 命令判断成员元素是否是集合的成员
*/
func (this *Redis) Sismember(key string, value interface{}) (iskeep bool, err error) {
iskeep, err = this.client.SIsMember(this.getContext(), key, value).Result()
return
}
/*
Redis Smembers 号召返回集合中的所有成员
*/
func (this *Redis) SMembers(valuetype reflect.Type, key string) (result []interface{}, err error) {
var _result []string
cmd := this.client.SMembers(this.getContext(), key)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Smove 命令将指定成员 member 元素从 source 集合移动到 destination 集合
SMOVE 是原子性操作
如果 source 集合不存在或不包含指定的 member 元素 SMOVE 命令不执行任何操作仅返回 0 否则 member 元素从 source 集合中被移除并添加到 destination 集合中去
destination 集合已经包含 member 元素时 SMOVE 命令只是简单地将 source 集合中的 member 元素删除
source destination 不是集合类型时返回一个错误
*/
func (this *Redis) SMove(source string, destination string, member interface{}) (result bool, err error) {
result, err = this.client.SMove(this.getContext(), source, destination, member).Result()
return
}
/*
Redis Spop命令用于移除集合中的指定键的一个或多个随机元素移除后会返回移除的元素
该命令类似于Srandmember命令但SPOP将随机元素从集合中移除并返回而Srandmember则返回元素而不是对集合进行任何改动
*/
func (this *Redis) Spop(key string) (result string, err error) {
result, err = this.client.SPop(this.getContext(), key).Result()
return
}
/*
Redis Srandmember 命令用于返回集合中的一个随机元素
Redis 2.6 版本开始 Srandmember 命令接受可选的 count 参数
如果 count 为正数且小于集合基数那么命令返回一个包含 count 个元素的数组数组中的元素各不相同如果 count 大于等于集合基数那么返回整个集合
如果 count 为负数那么命令返回一个数组数组中的元素可能会重复出现多次而数组的长度为 count 的绝对值
该操作和 SPOP 相似 SPOP 将随机元素从集合中移除并返回 Srandmember 则仅仅返回随机元素而不对集合进行任何改动
*/
func (this *Redis) Srandmember(key string) (result string, err error) {
result, err = this.client.SRandMember(this.getContext(), key).Result()
return
}
/*
Redis Srem 呼吁用于移除集合中的一个或多个元素元素不存在的元素元素会被忽略
当键不是集合类型返回一个错误
Redis 2.4 版本以前SREM 只接受个别成员值
*/
func (this *Redis) SRem(key string, members ...interface{}) (result int64, err error) {
result, err = this.client.SRem(this.getContext(), key, members...).Result()
return
}
/*
Redis Sunion 命令返回给定集合的并集
*/
func (this *Redis) SUnion(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
var _result []string
cmd := this.client.SUnion(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis Sunionstore 命令将给定集合的并集存储在指定的集合 destination 如果 destination 已经存在则将其覆盖
*/
func (this *Redis) Sunionstore(destination string, keys ...string) (result int64, err error) {
result, err = this.client.SUnionStore(this.getContext(), destination, keys...).Result()
return
}
/*
Redis Sscan 用于继承集合中键的元素Sscan 继承自Scan
*/
func (this *Redis) Sscan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) {
keys, cursor, err = this.client.SScan(this.getContext(), key, _cursor, match, count).Result()
return
}

View File

@ -0,0 +1,180 @@
package cluster
import (
"fmt"
"time"
"github.com/go-redis/redis/v8"
)
/* String *******************************************************************************/
/*
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Set(key string, value interface{}, expiration time.Duration) (err error) {
var result []byte
if result, err = this.Encode(value); err == nil {
err = this.client.Set(this.getContext(), string(key), result, expiration).Err()
}
return
}
/*
指定的 key 不存在时 key 设置指定的值
*/
func (this *Redis) SetNX(key string, value interface{}) (result int64, err error) {
// var _value []byte
// if result, err = this.Encode(value); err == nil {
// err = this.client.Do(this.getContext(), "SETNX", key, result).Err()
cmd := redis.NewIntCmd(this.getContext(), "SETNX", key, value)
this.client.Process(this.getContext(), cmd)
result, err = cmd.Result()
// }
return
}
/*
同时设置一个或多个 key-value
*/
func (this *Redis) MSet(keyvalues map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSET")
for k, v := range keyvalues {
result, _ := this.Encode(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
命令用于所有给定 key 都不存在时同时设置一个或多个 key-value
*/
func (this *Redis) MSetNX(keyvalues map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSETNX")
for k, v := range keyvalues {
result, _ := this.Encode(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
return
}
/*
Redis Incr 命令将 key 中储存的数字值增一
如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 INCR 操作
如果值包含错误的类型或字符串类型的值不能表示为数字那么返回一个错误
本操作的值限制在 64 (bit)有符号数字表示之内
*/
func (this *Redis) Incr(key string) (err error) {
err = this.client.Do(this.getContext(), "INCR", key).Err()
return
}
/*
Redis Incrby 命令将 key 中储存的数字加上指定的增量值
如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 INCRBY 命令
如果值包含错误的类型或字符串类型的值不能表示为数字那么返回一个错误
本操作的值限制在 64 (bit)有符号数字表示之内
*/
func (this *Redis) IncrBY(key string, value int) (err error) {
err = this.client.Do(this.getContext(), "INCRBY", key, value).Err()
return
}
/*
Redis Incrbyfloat 命令为 key 中所储存的值加上指定的浮点数增量值
如果 key 不存在那么 INCRBYFLOAT 会先将 key 的值设为 0 再执行加法操作
*/
func (this *Redis) Incrbyfloat(key string, value float32) (err error) {
err = this.client.Do(this.getContext(), "INCRBYFLOAT", key, value).Err()
return
}
/*
Redis Decr 命令将 key 中储存的数字值减一
如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 DECR 操作
如果值包含错误的类型或字符串类型的值不能表示为数字那么返回一个错误
本操作的值限制在 64 (bit)有符号数字表示之内
*/
func (this *Redis) Decr(key string, value int) (err error) {
err = this.client.Do(this.getContext(), "DECR", key, value).Err()
return
}
/*
Redis Decrby 命令将 key 所储存的值减去指定的减量值
如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 DECRBY 操作
如果值包含错误的类型或字符串类型的值不能表示为数字那么返回一个错误
本操作的值限制在 64 (bit)有符号数字表示之内
*/
func (this *Redis) DecrBy(key string, value int) (err error) {
err = this.client.Do(this.getContext(), "DECRBY", key, value).Err()
return
}
/*
Redis Append 命令用于为指定的 key 追加值
如果 key 已经存在并且是一个字符串 APPEND 命令将 value 追加到 key 原来的值的末尾
如果 key 不存在 APPEND 就简单地将给定 key 设为 value 就像执行 SET key value 一样
*/
func (this *Redis) Append(key string, value interface{}) (err error) {
var result []byte
if result, err = this.Encode(value); err == nil {
err = this.client.Do(this.getContext(), "APPEND", key, result).Err()
}
return
}
/*
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Get(key string, value interface{}) (err error) {
var result []byte
if result, err = this.client.Get(this.getContext(), key).Bytes(); err == nil {
err = this.Decode(result, value)
}
return
}
/*
设置指定 key 的值并返回 key 的旧值
*/
func (this *Redis) GetSet(key string, value interface{}, result interface{}) (err error) {
var (
data string
_value []byte
)
if _value, err = this.Encode(value); err == nil {
if data = this.client.Do(this.getContext(), "GETSET", key, _value).String(); data != string(redis.Nil) {
err = this.Decode([]byte(data), result)
} else {
err = fmt.Errorf(string(redis.Nil))
}
}
return
}
/*
返回所有(一个或多个)给定 key 的值 如果给定的 key 里面有某个 key 不存在那么这个 key 返回特殊值 nil
*/
func (this *Redis) MGet(keys ...string) (result []string, err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MGET")
for _, v := range keys {
agrs = append(agrs, v)
}
cmd := redis.NewStringSliceCmd(this.getContext(), agrs...)
this.client.Process(this.getContext(), cmd)
result, err = cmd.Result()
return
}
///判断是否存在key pattern:key*
func (this *Redis) INCRBY(key string, amount int64) (result int64, err error) {
cmd := redis.NewIntCmd(this.getContext(), "INCRBY", key, amount)
this.client.Process(this.getContext(), cmd)
result, err = cmd.Result()
return
}

View File

@ -0,0 +1,217 @@
package cluster
import (
"reflect"
"github.com/go-redis/redis/v8"
)
/*
Redis ZAdd 向有序集合添加一个或多个成员或者更新已存在成员的分数
*/
func (this *Redis) ZAdd(key string, members ...*redis.Z) (err error) {
this.client.ZAdd(this.getContext(), key, members...)
return
}
/*
Redis Zcard 用于计算集合中元素的数量
*/
func (this *Redis) ZCard(key string) (result int64, err error) {
result, err = this.client.ZCard(this.getContext(), key).Result()
return
}
/*
Redis ZCount 用于计算集合中指定的范围内的数量
*/
func (this *Redis) ZCount(key string, min string, max string) (result int64, err error) {
result, err = this.client.ZCount(this.getContext(), key, min, max).Result()
return
}
/*
Redis ZIncrBy 有序集合中对指定成员的分数加上增量 increment
*/
func (this *Redis) ZIncrBy(key string, increment float64, member string) (result float64, err error) {
result, err = this.client.ZIncrBy(this.getContext(), key, increment, member).Result()
return
}
/*
Redis ZInterStore 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination
*/
func (this *Redis) ZInterStore(destination string, store *redis.ZStore) (result int64, err error) {
result, err = this.client.ZInterStore(this.getContext(), destination, store).Result()
return
}
/*
Redis ZLexCount 在有序集合中计算指定字典区间内成员数量
*/
func (this *Redis) ZLexCount(key string, min string, max string) (result int64, err error) {
result, err = this.client.ZLexCount(this.getContext(), key, min, max).Result()
return
}
/*
Redis ZRange 通过索引区间返回有序集合指定区间内的成员
*/
func (this *Redis) ZRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error) {
var _result []string
cmd := this.client.ZRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis ZRangeByLex 通过字典区间返回有序集合的成员
*/
func (this *Redis) ZRangeByLex(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
var _result []string
cmd := this.client.ZRangeByLex(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis ZRangeByScore 通过分数返回有序集合指定区间内的成员
*/
func (this *Redis) ZRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
var _result []string
cmd := this.client.ZRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis ZRank 返回有序集合中指定成员的索引
*/
func (this *Redis) ZRank(key string, member string) (result int64, err error) {
result, err = this.client.ZRank(this.getContext(), key, member).Result()
return
}
/*
Redis ZRem 移除有序集合中的一个或多个成员
*/
func (this *Redis) ZRem(key string, members ...interface{}) (result int64, err error) {
result, err = this.client.ZRem(this.getContext(), key, members...).Result()
return
}
/*
Redis ZRemRangeByLex 移除有序集合中给定的字典区间的所有成员
*/
func (this *Redis) ZRemRangeByLex(key string, min string, max string) (result int64, err error) {
result, err = this.client.ZRemRangeByLex(this.getContext(), key, min, max).Result()
return
}
/*
Redis ZRemRangeByRank 移除有序集合中给定的排名区间的所有成员
*/
func (this *Redis) ZRemRangeByRank(key string, start int64, stop int64) (result int64, err error) {
result, err = this.client.ZRemRangeByRank(this.getContext(), key, start, stop).Result()
return
}
/*
Redis ZRemRangeByScore 移除有序集合中给定的分数区间的所有成员
*/
func (this *Redis) ZRemRangeByScore(key string, min string, max string) (result int64, err error) {
result, err = this.client.ZRemRangeByScore(this.getContext(), key, min, max).Result()
return
}
/*
Redis ZRevRange 返回有序集中指定区间内的成员通过索引分数从高到低 ZREVRANGE
*/
func (this *Redis) ZRevRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error) {
var _result []string
cmd := this.client.ZRevRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis ZRevRangeByScore 返回有序集中指定分数区间内的成员分数从高到低排序
*/
func (this *Redis) ZRevRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
var _result []string
cmd := this.client.ZRevRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
result = make([]interface{}, len(_result))
for i, v := range _result {
temp := reflect.New(valuetype.Elem()).Interface()
if err = this.Decode([]byte(v), &temp); err == nil {
result[i] = temp
}
}
}
return
}
/*
Redis ZRevRank 返回有序集中指定分数区间内的成员分数从高到低排序
*/
func (this *Redis) ZRevRank(key string, member string) (result int64, err error) {
result, err = this.client.ZRevRank(this.getContext(), key, member).Result()
return
}
/*
Redis ZScore 返回有序集中指定分数区间内的成员分数从高到低排序
*/
func (this *Redis) ZScore(key string, member string) (result float64, err error) {
result, err = this.client.ZScore(this.getContext(), key, member).Result()
return
}
/*
Redis ZScore 返回有序集中指定分数区间内的成员分数从高到低排序 ZUNIONSTORE
*/
func (this *Redis) ZUnionStore(dest string, store *redis.ZStore) (result int64, err error) {
result, err = this.client.ZUnionStore(this.getContext(), dest, store).Result()
return
}
/*
Redis ZScan 迭代有序集合中的元素包括元素成员和元素分值
*/
func (this *Redis) ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) {
keys, cursor, err = this.client.ZScan(this.getContext(), key, _cursor, match, count).Result()
return
}

453
lego/sys/redis/core.go Normal file
View File

@ -0,0 +1,453 @@
package redis
import (
"context"
"reflect"
"time"
"github.com/go-redis/redis/v8"
)
type (
IRedis interface {
Close() (err error)
Do(ctx context.Context, args ...interface{}) *redis.Cmd
Lock(key string, outTime int) (result bool, err error)
UnLock(key string) (err error)
Pipeline(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error)
TxPipelined(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error)
Watch(ctx context.Context, fn func(*redis.Tx) error, keys ...string) (err error)
/*Key*/
Delete(key string) (err error)
ExistsKey(key string) (iskeep bool, err error)
ExpireKey(key string, expire int) (err error)
ExpireatKey(key string, expire_unix int64) (err error)
Pexpirekey(key string, expire int) (err error)
PexpireatKey(key string, expire_unix int64) (err error)
PersistKey(key string) (err error)
PttlKey(key string) (leftexpire int64, err error)
TtlKey(key string) (leftexpire int64, err error)
RenameKye(oldkey string, newkey string) (err error)
RenamenxKey(oldkey string, newkey string) (err error)
Keys(pattern string) (keys []string, err error)
Type(key string) (ty string, err error)
/*String*/
Set(key string, value interface{}, expiration time.Duration) (err error)
SetNX(key string, value interface{}) (result int64, err error)
MSet(keyvalues map[string]interface{}) (err error)
MSetNX(keyvalues map[string]interface{}) (err error)
Incr(key string) (err error)
IncrBY(key string, value int) (err error)
Incrbyfloat(key string, value float32) (err error)
Decr(key string, value int) (err error)
DecrBy(key string, value int) (err error)
Append(key string, value interface{}) (err error)
Get(key string, value interface{}) (err error)
GetSet(key string, value interface{}, result interface{}) (err error)
MGet(keys ...string) (result []string, err error)
INCRBY(key string, amount int64) (result int64, err error)
/*List*/
Lindex(key string, value interface{}) (err error)
Linsert(key string, isbefore bool, tager interface{}, value interface{}) (err error)
Llen(key string) (result int, err error)
LPop(key string, value interface{}) (err error)
LPush(key string, values ...interface{}) (err error)
LPushX(key string, values ...interface{}) (err error)
LRange(key string, start, end int, valuetype reflect.Type) (result []interface{}, err error)
LRem(key string, count int, target interface{}) (err error)
LSet(key string, index int, value interface{}) (err error)
Ltrim(key string, start, stop int) (err error)
Rpop(key string, value interface{}) (err error)
RPopLPush(oldkey string, newkey string, value interface{}) (err error)
RPush(key string, values ...interface{}) (err error)
RPushX(key string, values ...interface{}) (err error)
/*Hash*/
HDel(key string, fields ...string) (err error)
HExists(key string, field string) (result bool, err error)
HGet(key string, field string, value interface{}) (err error)
HGetAll(key string, valuetype reflect.Type) (result []interface{}, err error)
HIncrBy(key string, field string, value int) (err error)
HIncrByFloat(key string, field string, value float32) (err error)
Hkeys(key string) (result []string, err error)
Hlen(key string) (result int, err error)
HMGet(key string, valuetype reflect.Type, fields ...string) (result []interface{}, err error)
HMSet(key string, value map[string]interface{}) (err error)
HSet(key string, field string, value interface{}) (err error)
HSetNX(key string, field string, value interface{}) (err error)
/*Set*/
SAdd(key string, values ...interface{}) (err error)
SCard(key string) (result int64, err error)
SDiff(valuetype reflect.Type, keys ...string) (result []interface{}, err error)
SDiffStore(destination string, keys ...string) (result int64, err error)
SInter(valuetype reflect.Type, keys ...string) (result []interface{}, err error)
SInterStore(destination string, keys ...string) (result int64, err error)
Sismember(key string, value interface{}) (iskeep bool, err error)
SMembers(valuetype reflect.Type, key string) (result []interface{}, err error)
SMove(source string, destination string, member interface{}) (result bool, err error)
Spop(key string) (result string, err error)
Srandmember(key string) (result string, err error)
SRem(key string, members ...interface{}) (result int64, err error)
SUnion(valuetype reflect.Type, keys ...string) (result []interface{}, err error)
Sunionstore(destination string, keys ...string) (result int64, err error)
Sscan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error)
/*ZSet*/
ZAdd(key string, members ...*redis.Z) (err error)
ZCard(key string) (result int64, err error)
ZCount(key string, min string, max string) (result int64, err error)
ZIncrBy(key string, increment float64, member string) (result float64, err error)
ZInterStore(destination string, store *redis.ZStore) (result int64, err error)
ZLexCount(key string, min string, max string) (result int64, err error)
ZRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error)
ZRangeByLex(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error)
ZRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error)
ZRank(key string, member string) (result int64, err error)
ZRem(key string, members ...interface{}) (result int64, err error)
ZRemRangeByLex(key string, min string, max string) (result int64, err error)
ZRemRangeByRank(key string, start int64, stop int64) (result int64, err error)
ZRemRangeByScore(key string, min string, max string) (result int64, err error)
ZRevRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error)
ZRevRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error)
ZRevRank(key string, member string) (result int64, err error)
ZScore(key string, member string) (result float64, err error)
ZUnionStore(dest string, store *redis.ZStore) (result int64, err error)
ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error)
}
ISys interface {
IRedis
Encode(value interface{}) (result []byte, err error)
Decode(value []byte, result interface{}) (err error)
/*Lock*/
NewRedisMutex(key string, opt ...RMutexOption) (result *RedisMutex, err error)
}
)
const (
RedisNil = redis.Nil //数据为空错误
TxFailedErr = redis.TxFailedErr
)
var defsys ISys
func OnInit(config map[string]interface{}, option ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func Close() (err error) {
return defsys.Close()
}
func Do(ctx context.Context, args ...interface{}) *redis.Cmd {
return defsys.Do(ctx, args...)
}
func Pipeline(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) {
return defsys.Pipeline(ctx, fn)
}
func TxPipelined(ctx context.Context, fn func(pipe redis.Pipeliner) error) (err error) {
return defsys.TxPipelined(ctx, fn)
}
func Watch(ctx context.Context, fn func(*redis.Tx) error, keys ...string) (err error) {
return defsys.Watch(ctx, fn)
}
func Encode(value interface{}) (result []byte, err error) {
return defsys.Encode(value)
}
func Decode(value []byte, result interface{}) (err error) {
return defsys.Decode(value, result)
}
func Delete(key string) (err error) {
return defsys.Delete(key)
}
func ExistsKey(key string) (iskeep bool, err error) {
return defsys.ExistsKey(key)
}
func ExpireKey(key string, expire int) (err error) {
return defsys.ExpireKey(key, expire)
}
func ExpireatKey(key string, expire_unix int64) (err error) {
return defsys.ExpireatKey(key, expire_unix)
}
func Pexpirekey(key string, expire int) (err error) {
return defsys.Pexpirekey(key, expire)
}
func PexpireatKey(key string, expire_unix int64) (err error) {
return defsys.PexpireatKey(key, expire_unix)
}
func PersistKey(key string) (err error) {
return defsys.PersistKey(key)
}
func PttlKey(key string) (leftexpire int64, err error) {
return defsys.PttlKey(key)
}
func TtlKey(key string) (leftexpire int64, err error) {
return defsys.TtlKey(key)
}
func RenameKye(oldkey string, newkey string) (err error) {
return defsys.RenameKye(oldkey, newkey)
}
func RenamenxKey(oldkey string, newkey string) (err error) {
return defsys.RenamenxKey(oldkey, newkey)
}
func Keys(pattern string) (keys []string, err error) {
return defsys.Keys(pattern)
}
///获取键类型
func Type(key string) (ty string, err error) {
return defsys.Type(key)
}
/*String*/
func Set(key string, value interface{}, expiration time.Duration) (err error) {
return defsys.Set(key, value, expiration)
}
func SetNX(key string, value interface{}) (result int64, err error) {
return defsys.SetNX(key, value)
}
func MSet(keyvalues map[string]interface{}) (err error) {
return defsys.MSet(keyvalues)
}
func MSetNX(keyvalues map[string]interface{}) (err error) {
return defsys.MSetNX(keyvalues)
}
func Incr(key string) (err error) {
return defsys.Incr(key)
}
func IncrBY(key string, value int) (err error) {
return defsys.IncrBY(key, value)
}
func Incrbyfloat(key string, value float32) (err error) {
return defsys.Incrbyfloat(key, value)
}
func Decr(key string, value int) (err error) {
return defsys.Decr(key, value)
}
func DecrBy(key string, value int) (err error) {
return defsys.DecrBy(key, value)
}
func Append(key string, value interface{}) (err error) {
return defsys.Append(key, value)
}
func Get(key string, value interface{}) (err error) {
return defsys.Get(key, value)
}
func GetSet(key string, value interface{}, result interface{}) (err error) {
return defsys.GetSet(key, value, result)
}
func MGet(keys ...string) (result []string, err error) {
return defsys.MGet(keys...)
}
func INCRBY(key string, amount int64) (result int64, err error) {
return defsys.INCRBY(key, amount)
}
/*Lock*/
func NewRedisMutex(key string, opt ...RMutexOption) (result *RedisMutex, err error) {
return defsys.NewRedisMutex(key, opt...)
}
func Lock(key string, outTime int) (result bool, err error) {
return defsys.Lock(key, outTime)
}
func UnLock(key string) (err error) {
return defsys.UnLock(key)
}
/*List*/
func Lindex(key string, value interface{}) (err error) {
return defsys.Lindex(key, value)
}
func Linsert(key string, isbefore bool, tager interface{}, value interface{}) (err error) {
return defsys.Linsert(key, isbefore, tager, value)
}
func Llen(key string) (result int, err error) {
return defsys.Llen(key)
}
func LPop(key string, value interface{}) (err error) {
return defsys.LPop(key, value)
}
func LPush(key string, values ...interface{}) (err error) {
return defsys.LPush(key, values...)
}
func LPushX(key string, values ...interface{}) (err error) {
return defsys.LPushX(key, values...)
}
func LRange(key string, start, end int, valuetype reflect.Type) (result []interface{}, err error) {
return defsys.LRange(key, start, end, valuetype)
}
func LRem(key string, count int, target interface{}) (err error) {
return defsys.LRem(key, count, target)
}
func LSet(key string, index int, value interface{}) (err error) {
return defsys.LSet(key, index, value)
}
func Ltrim(key string, start, stop int) (err error) {
return defsys.Ltrim(key, start, stop)
}
func Rpop(key string, value interface{}) (err error) {
return defsys.Rpop(key, value)
}
func RPopLPush(oldkey string, newkey string, value interface{}) (err error) {
return defsys.RPopLPush(oldkey, newkey, value)
}
func RPush(key string, values ...interface{}) (err error) {
return defsys.RPush(key, values...)
}
func RPushX(key string, values ...interface{}) (err error) {
return defsys.RPushX(key, values...)
}
/*Hash*/
func HDel(key string, fields ...string) (err error) {
return defsys.HDel(key, fields...)
}
func HExists(key string, field string) (result bool, err error) {
return defsys.HExists(key, field)
}
func HGet(key string, field string, value interface{}) (err error) {
return defsys.HGet(key, field, value)
}
func HGetAll(key string, valuetype reflect.Type) (result []interface{}, err error) {
return defsys.HGetAll(key, valuetype)
}
func HIncrBy(key string, field string, value int) (err error) {
return defsys.HIncrBy(key, field, value)
}
func HIncrByFloat(key string, field string, value float32) (err error) {
return defsys.HIncrByFloat(key, field, value)
}
func Hkeys(key string) (result []string, err error) {
return defsys.Hkeys(key)
}
func Hlen(key string) (result int, err error) {
return defsys.Hlen(key)
}
func HMGet(key string, valuetype reflect.Type, fields ...string) (result []interface{}, err error) {
return defsys.HMGet(key, valuetype, fields...)
}
func HMSet(key string, value map[string]interface{}) (err error) {
return defsys.HMSet(key, value)
}
func HSet(key string, field string, value interface{}) (err error) {
return defsys.HSet(key, field, value)
}
func HSetNX(key string, field string, value interface{}) (err error) {
return defsys.HSetNX(key, field, value)
}
/*Set*/
func SAdd(key string, values ...interface{}) (err error) {
return defsys.SAdd(key, values...)
}
func SCard(key string) (result int64, err error) {
return defsys.SCard(key)
}
func SDiff(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
return defsys.SDiff(valuetype, keys...)
}
func SDiffStore(destination string, keys ...string) (result int64, err error) {
return defsys.SDiffStore(destination, keys...)
}
func SInter(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
return defsys.SInter(valuetype, keys...)
}
func SInterStore(destination string, keys ...string) (result int64, err error) {
return defsys.SInterStore(destination, keys...)
}
func Sismember(key string, value interface{}) (iskeep bool, err error) {
return defsys.Sismember(key, value)
}
func SMembers(valuetype reflect.Type, key string) (result []interface{}, err error) {
return defsys.SMembers(valuetype, key)
}
func SMove(source string, destination string, member interface{}) (result bool, err error) {
return defsys.SMove(source, destination, member)
}
func Spop(key string) (result string, err error) {
return defsys.Spop(key)
}
func Srandmember(key string) (result string, err error) {
return defsys.Srandmember(key)
}
func SRem(key string, members ...interface{}) (result int64, err error) {
return defsys.SRem(key, members...)
}
func SUnion(valuetype reflect.Type, keys ...string) (result []interface{}, err error) {
return defsys.SUnion(valuetype, keys...)
}
func Sunionstore(destination string, keys ...string) (result int64, err error) {
return defsys.Sunionstore(destination, keys...)
}
func Sscan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) {
return defsys.Sscan(key, _cursor, match, count)
}
/*ZSet*/
func ZAdd(key string, members ...*redis.Z) (err error) {
return defsys.ZAdd(key, members...)
}
func ZCard(key string) (result int64, err error) {
return defsys.ZCard(key)
}
func ZCount(key string, min string, max string) (result int64, err error) {
return defsys.ZCount(key, min, max)
}
func ZIncrBy(key string, increment float64, member string) (result float64, err error) {
return defsys.ZIncrBy(key, increment, member)
}
func ZInterStore(destination string, store *redis.ZStore) (result int64, err error) {
return defsys.ZInterStore(destination, store)
}
func ZLexCount(key string, min string, max string) (result int64, err error) {
return defsys.ZLexCount(key, min, max)
}
func ZRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error) {
return defsys.ZRange(valuetype, key, start, stop)
}
func ZRangeByLex(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
return defsys.ZRangeByLex(valuetype, key, opt)
}
func ZRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
return defsys.ZRangeByScore(valuetype, key, opt)
}
func ZRank(key string, member string) (result int64, err error) {
return defsys.ZRank(key, member)
}
func ZRem(key string, members ...interface{}) (result int64, err error) {
return defsys.ZRem(key, members...)
}
func ZRemRangeByLex(key string, min string, max string) (result int64, err error) {
return defsys.ZRemRangeByLex(key, min, max)
}
func ZRemRangeByRank(key string, start int64, stop int64) (result int64, err error) {
return defsys.ZRemRangeByRank(key, start, stop)
}
func ZRemRangeByScore(key string, min string, max string) (result int64, err error) {
return defsys.ZRemRangeByScore(key, min, max)
}
func ZRevRange(valuetype reflect.Type, key string, start int64, stop int64) (result []interface{}, err error) {
return defsys.ZRevRange(valuetype, key, start, stop)
}
func ZRevRangeByScore(valuetype reflect.Type, key string, opt *redis.ZRangeBy) (result []interface{}, err error) {
return defsys.ZRevRangeByScore(valuetype, key, opt)
}
func ZRevRank(key string, member string) (result int64, err error) {
return defsys.ZRevRank(key, member)
}
func ZScore(key string, member string) (result float64, err error) {
return defsys.ZScore(key, member)
}
func ZUnionStore(dest string, store *redis.ZStore) (result int64, err error) {
return defsys.ZUnionStore(dest, store)
}
func ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) {
return defsys.ZScan(key, _cursor, match, count)
}

53
lego/sys/redis/lock.go Normal file
View File

@ -0,0 +1,53 @@
package redis
import (
"errors"
"time"
)
/*
Redis Scard 命令返回集合中元素的数量
*/
func (this *Redis) NewRedisMutex(key string, opt ...RMutexOption) (result *RedisMutex, err error) {
opts := newRMutexOptions(opt...)
result = &RedisMutex{
sys: this.client,
key: key,
expiry: opts.expiry,
delay: opts.delay,
}
return
}
type RedisMutex struct {
sys IRedis
key string
expiry int //过期时间 单位秒
delay time.Duration
}
//此接口未阻塞接口
func (this *RedisMutex) Lock() (err error) {
wait := make(chan error)
go func() {
start := time.Now()
for int(time.Now().Sub(start).Seconds()) <= this.expiry {
if result, err := this.sys.Lock(this.key, this.expiry); err == nil && result {
wait <- nil
return
} else if err == nil && !result {
time.Sleep(this.delay)
} else {
wait <- err
return
}
}
wait <- errors.New("time out")
}()
err = <-wait
return
}
func (this *RedisMutex) Unlock() {
this.sys.UnLock(this.key)
}

Some files were not shown because too many files have changed in this diff Show More