Pārlūkot izejas kodu

Merge branch 'master' of https://git.sxidc.com/go-tools/utils

duyong mac 4 mēneši atpakaļ
vecāks
revīzija
d281074a6a

+ 17 - 0
encoding/encoding.go

@@ -10,9 +10,18 @@ import (
 	"encoding/base64"
 	"encoding/hex"
 	"fmt"
+	"git.sxidc.com/go-tools/utils/strutils"
 )
 
 func AESEncrypt(originData string, key string) (string, error) {
+	if strutils.IsStringEmpty(originData) {
+		return "", nil
+	}
+
+	if strutils.IsStringEmpty(key) {
+		return originData, nil
+	}
+
 	keyBytes := []byte(key)
 
 	block, err := aes.NewCipher(keyBytes)
@@ -31,6 +40,14 @@ func AESEncrypt(originData string, key string) (string, error) {
 }
 
 func AESDecrypt(encrypted string, key string) (string, error) {
+	if strutils.IsStringEmpty(encrypted) {
+		return "", nil
+	}
+
+	if strutils.IsStringEmpty(key) {
+		return encrypted, nil
+	}
+
 	keyBytes := []byte(key)
 
 	block, err := aes.NewCipher(keyBytes)

+ 2 - 26
go.mod

@@ -3,7 +3,6 @@ module git.sxidc.com/go-tools/utils
 go 1.21.3
 
 require (
-	git.sxidc.com/service-supports/fslog v0.5.9
 	github.com/Masterminds/sprig/v3 v3.2.3
 	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3
@@ -13,6 +12,8 @@ require (
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
 	github.com/mitchellh/mapstructure v1.5.0
 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
+	github.com/olahol/melody v1.2.1
+	github.com/pkg/errors v0.9.1
 	github.com/redis/go-redis/v9 v9.4.0
 	github.com/satori/go.uuid v1.2.0
 	github.com/shopspring/decimal v1.2.0
@@ -24,50 +25,25 @@ require (
 require (
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.2.0 // indirect
-	github.com/bytedance/sonic v1.10.0 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
-	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
-	github.com/chenzhuoyu/iasm v0.9.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
-	github.com/gin-contrib/sse v0.1.0 // indirect
-	github.com/gin-gonic/gin v1.9.1 // indirect
 	github.com/go-ego/gse v0.69.15 // indirect
-	github.com/go-playground/locales v0.14.1 // indirect
-	github.com/go-playground/universal-translator v0.18.1 // indirect
-	github.com/go-playground/validator/v10 v10.15.3 // indirect
-	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/google/uuid v1.1.1 // indirect
 	github.com/gorilla/websocket v1.5.0 // indirect
 	github.com/huandu/xstrings v1.3.3 // indirect
 	github.com/imdario/mergo v0.3.11 // indirect
-	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
-	github.com/leodido/go-urn v1.2.4 // indirect
-	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/mitchellh/copystructure v1.0.0 // indirect
 	github.com/mitchellh/reflectwalk v1.0.0 // indirect
-	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
-	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
-	github.com/pelletier/go-toml/v2 v2.1.0 // indirect
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/spf13/cast v1.3.1 // indirect
-	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
-	github.com/ugorji/go/codec v1.2.11 // indirect
 	github.com/vcaesar/cedar v0.20.0 // indirect
 	github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
 	github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
-	go.uber.org/multierr v1.11.0 // indirect
-	go.uber.org/zap v1.25.0 // indirect
-	golang.org/x/arch v0.5.0 // indirect
 	golang.org/x/crypto v0.19.0 // indirect
 	golang.org/x/net v0.21.0 // indirect
 	golang.org/x/sync v0.1.0 // indirect
-	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
-	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 )

+ 4 - 85
go.sum

@@ -1,5 +1,3 @@
-git.sxidc.com/service-supports/fslog v0.5.9 h1:q2XIK2o/fk/qmByy4x5kKLC+k7kolT5LrXHcWRSffXQ=
-git.sxidc.com/service-supports/fslog v0.5.9/go.mod h1:/m03ATmmOle75qtEgvEw8a1+Dcg6iHp08M1bGFXJTBU=
 github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
 github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
 github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
@@ -8,24 +6,12 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj
 github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
-github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
-github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
 github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
 github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
 github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
-github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
-github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
-github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
-github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
-github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
-github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
-github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
-github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
-github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -35,34 +21,14 @@ github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQ
 github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE=
 github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
-github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
-github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
-github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
-github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
 github.com/go-ego/gpy v0.42.1 h1:P/doarxZi2J5qwNzLIM0ESd3VXLXMpdhwO/GNontLdE=
 github.com/go-ego/gpy v0.42.1/go.mod h1:eBtY3/uCDqBFog4ES9L00xytTpXar/0mGf45Rb7zcgg=
 github.com/go-ego/gse v0.69.15 h1:QprXRGKim8fI2B38ItT4YwuY9/37gwUAw37TnA3exa0=
 github.com/go-ego/gse v0.69.15/go.mod h1:M9Xv8cEW7Of27BbE4p0iI3arqQHCYcm5N16/2b3pPPk=
-github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
-github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
-github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
-github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
-github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo=
-github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8=
 github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
-github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
-github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -71,33 +37,20 @@ github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4
 github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
 github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-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/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
-github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
-github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
-github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
-github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
-github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
+github.com/olahol/melody v1.2.1 h1:xdwRkzHxf+B0w4TKbGpUSSkV516ZucQZJIWLztOWICQ=
+github.com/olahol/melody v1.2.1/go.mod h1:GgkTl6Y7yWj/HtfD48Q5vLKPVoZOH+Qqgfa7CvJgJM4=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk=
@@ -114,22 +67,10 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
 github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
-github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
-github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
-github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/vcaesar/cedar v0.20.0 h1:VtBy/twzVjXiTo1Ij3fQRyDQRzvzDa9sKacpbwSJyps=
 github.com/vcaesar/cedar v0.20.0/go.mod h1:iMDweyuW76RvSrCkQeZeQk4iCbshiPzcCvcGCtpM7iI=
 github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA=
@@ -141,15 +82,6 @@ github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluU
 github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
 github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
-go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
-golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
-golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
@@ -180,11 +112,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -207,20 +136,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
-rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 1 - 1
http_client/request.go

@@ -2,8 +2,8 @@ package http_client
 
 import (
 	"encoding/json"
-	"errors"
 	"github.com/go-resty/resty/v2"
+	"github.com/pkg/errors"
 )
 
 type RequestOption func(request *Request)

+ 1 - 1
maputils/maputils.go

@@ -1,7 +1,7 @@
 package maputils
 
 import (
-	"errors"
+	"github.com/pkg/errors"
 	"strconv"
 	"strings"
 )

+ 1 - 1
mqtt_client/mqtt_client.go

@@ -2,9 +2,9 @@ package mqtt_client
 
 import (
 	"encoding/json"
-	"errors"
 	"git.sxidc.com/go-tools/utils/strutils"
 	mqtt "github.com/eclipse/paho.mqtt.golang"
+	"github.com/pkg/errors"
 	"log"
 	"sync"
 	"time"

+ 1 - 1
oss/oss.go

@@ -2,9 +2,9 @@ package oss
 
 import (
 	"bytes"
-	"errors"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+	"github.com/pkg/errors"
 	"io"
 	"log"
 )

+ 1 - 1
pipeline/component/component.go

@@ -1,8 +1,8 @@
 package component
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
 	"sync"
 )
 

+ 1 - 1
pipeline/component/flow/bi.go

@@ -1,9 +1,9 @@
 package flow
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
pipeline/component/flow/flow.go

@@ -1,9 +1,9 @@
 package flow
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
 )
 
 type SubComponentBuildParams struct {

+ 1 - 1
pipeline/component/flow/if.go

@@ -1,10 +1,10 @@
 package flow
 
 import (
-	"errors"
 	"fmt"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
pipeline/component/flow/loop.go

@@ -1,10 +1,10 @@
 package flow
 
 import (
-	"errors"
 	"fmt"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
pipeline/component/flow/range.go

@@ -1,9 +1,9 @@
 package flow
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
pipeline/component/flow/seq.go

@@ -1,9 +1,9 @@
 package flow
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
pipeline/definition.go

@@ -1,11 +1,11 @@
 package pipeline
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"git.sxidc.com/go-tools/utils/pipeline/component/flow"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"github.com/fatih/structs"
+	"github.com/pkg/errors"
 )
 
 type Definition struct {

+ 1 - 1
pipeline/pipeline.go

@@ -1,11 +1,11 @@
 package pipeline
 
 import (
-	"errors"
 	"git.sxidc.com/go-tools/utils/fileutils"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"git.sxidc.com/go-tools/utils/pipeline/component/flow"
 	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
 	"gopkg.in/yaml.v3"
 	"os"
 )

+ 1 - 1
pipeline/test/test_node/bool.go

@@ -1,11 +1,11 @@
 package test_node
 
 import (
-	"errors"
 	"fmt"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 	"math/rand"
 )
 

+ 1 - 1
pipeline/test/test_node/println.go

@@ -1,11 +1,11 @@
 package test_node
 
 import (
-	"errors"
 	"fmt"
 	"git.sxidc.com/go-tools/utils/pipeline/component"
 	"git.sxidc.com/go-tools/utils/pipeline/component/flow"
 	"github.com/mitchellh/mapstructure"
+	"github.com/pkg/errors"
 )
 
 const (

+ 1 - 1
redis_client/redis_client.go

@@ -2,7 +2,7 @@ package redis_client
 
 import (
 	"context"
-	"errors"
+	"github.com/pkg/errors"
 	"github.com/redis/go-redis/v9"
 	"time"
 )

+ 1 - 1
redislock/lock.go

@@ -2,7 +2,7 @@ package redislock
 
 import (
 	"context"
-	"errors"
+	"github.com/pkg/errors"
 	"github.com/redis/go-redis/v9"
 	"time"
 )

+ 221 - 0
reflectutils/maker.go

@@ -0,0 +1,221 @@
+package reflectutils
+
+import (
+	"fmt"
+	"reflect"
+)
+
+type StructFieldDefinition struct {
+	Name string
+	Type reflect.Type
+	Tag  string
+}
+
+type StructMethodDefinition struct {
+	Name             string
+	ArgTypes         []reflect.Type
+	ReturnValueTypes []reflect.Type
+	Body             func(this *Struct, args ...any) []any
+}
+
+type Struct struct {
+	structValueElem reflect.Value
+	fieldMap        map[string]reflect.Value
+	methodMap       map[string]reflect.Value
+}
+
+func NewStruct(fields ...StructFieldDefinition) *Struct {
+	if len(fields) == 0 {
+		return &Struct{
+			structValueElem: reflect.ValueOf(struct{}{}),
+		}
+	}
+
+	reflectStructFields := make([]reflect.StructField, len(fields))
+	for i, field := range fields {
+		reflectStructFields[i] = reflect.StructField{
+			Name: field.Name,
+			Type: field.Type,
+			Tag:  reflect.StructTag(field.Tag),
+		}
+	}
+
+	return &Struct{
+		structValueElem: reflect.New(reflect.StructOf(reflectStructFields)).Elem(),
+		fieldMap:        map[string]reflect.Value{},
+		methodMap:       map[string]reflect.Value{},
+	}
+}
+
+func (s *Struct) Any() any {
+	return s.structValueElem.Interface()
+}
+
+func (s *Struct) Pointer() any {
+	return s.structValueElem.Addr().Interface()
+}
+
+func (s *Struct) SetFieldValue(fieldName string, value any) {
+	s.loadFieldValue(fieldName).Set(reflect.ValueOf(value))
+}
+
+func (s *Struct) FieldValue(fieldName string) any {
+	return s.loadFieldValue(fieldName).Interface()
+}
+
+func (s *Struct) SetFieldValues(fieldAndValues map[string]any) {
+	for fieldName, value := range fieldAndValues {
+		s.SetFieldValue(fieldName, value)
+	}
+}
+
+func (s *Struct) FieldValues(fieldNames ...string) map[string]any {
+	if len(fieldNames) == 0 {
+		return map[string]any{}
+	}
+
+	fieldAndValues := make(map[string]any)
+	for _, fieldName := range fieldNames {
+		fieldAndValues[fieldName] = s.FieldValue(fieldName)
+	}
+
+	return fieldAndValues
+}
+
+func (s *Struct) MakeMethod(methods ...StructMethodDefinition) {
+	for _, method := range methods {
+		argTypes := make([]reflect.Type, 0)
+		argTypes = append(argTypes, s.structValueElem.Type())
+		argTypes = append(argTypes, method.ArgTypes...)
+
+		funcValue := reflect.MakeFunc(reflect.FuncOf(argTypes, method.ReturnValueTypes, false),
+			func(argValues []reflect.Value) []reflect.Value {
+				args := make([]any, len(argValues)-1)
+				for i, arg := range argValues {
+					if i == 0 {
+						continue
+					}
+
+					args[i-1] = arg.Interface()
+				}
+
+				returns := method.Body(s, args)
+
+				returnValues := make([]reflect.Value, len(returns))
+				for j, returnValue := range returns {
+					reflectValue := reflect.ValueOf(returnValue)
+					if !reflectValue.IsValid() {
+						returnValues[j] = reflect.Zero(method.ReturnValueTypes[j])
+					} else {
+						returnValues[j] = reflect.ValueOf(returnValue)
+					}
+				}
+
+				return returnValues
+			})
+
+		s.methodMap[method.Name] = funcValue
+	}
+}
+
+func (s *Struct) CallMethod(methodName string, args ...any) []any {
+	method, ok := s.methodMap[methodName]
+	if !ok {
+		panic(fmt.Sprintf("%s方法不存在", methodName))
+	}
+
+	argValues := make([]reflect.Value, len(args)+1)
+	argValues[0] = s.structValueElem
+	for i, arg := range args {
+		argValues[i+1] = reflect.ValueOf(arg)
+	}
+
+	returnValues := method.Call(argValues)
+
+	returns := make([]any, len(returnValues))
+	for j, returnValue := range returnValues {
+		if returnValue.IsNil() {
+			returns[j] = nil
+		} else {
+			returns[j] = returnValue.Interface()
+		}
+	}
+
+	return returns
+}
+
+func (s *Struct) loadFieldValue(fieldName string) reflect.Value {
+	fieldValue, ok := s.fieldMap[fieldName]
+	if ok {
+		return fieldValue
+	}
+
+	fieldValue = s.structValueElem.FieldByName(fieldName)
+	if !fieldValue.IsValid() {
+		panic(fmt.Sprintf("%s字段不存在", fieldName))
+	}
+
+	return fieldValue
+}
+
+type FunctionDefinition struct {
+	ArgTypes         []reflect.Type
+	ReturnValueTypes []reflect.Type
+	Body             func(args ...any) []any
+}
+
+type Function struct {
+	functionValue reflect.Value
+}
+
+func (f *Function) Call(args ...any) []any {
+	argValues := make([]reflect.Value, len(args))
+	for i, arg := range args {
+		argValues[i] = reflect.ValueOf(arg)
+	}
+
+	returnValues := f.functionValue.Call(argValues)
+
+	returns := make([]any, len(returnValues))
+	for j, returnValue := range returnValues {
+		if returnValue.IsNil() {
+			returns[j] = nil
+		} else {
+			returns[j] = returnValue.Interface()
+		}
+	}
+
+	return returns
+}
+
+func MakeFunction(function FunctionDefinition) *Function {
+	funcValue := reflect.MakeFunc(reflect.FuncOf(function.ArgTypes, function.ReturnValueTypes, false),
+		func(argValues []reflect.Value) []reflect.Value {
+			args := make([]any, len(argValues)-1)
+			for i, arg := range argValues {
+				if i == 0 {
+					continue
+				}
+
+				args[i-1] = arg.Interface()
+			}
+
+			returns := function.Body(args)
+
+			returnValues := make([]reflect.Value, len(returns))
+			for j, returnValue := range returns {
+				reflectValue := reflect.ValueOf(returnValue)
+				if !reflectValue.IsValid() {
+					returnValues[j] = reflect.Zero(function.ReturnValueTypes[j])
+				} else {
+					returnValues[j] = reflect.ValueOf(returnValue)
+				}
+			}
+
+			return returnValues
+		})
+
+	return &Function{
+		functionValue: funcValue,
+	}
+}

+ 100 - 0
reflectutils/maker_test.go

@@ -0,0 +1,100 @@
+package reflectutils
+
+import (
+	"fmt"
+	"github.com/pkg/errors"
+	"reflect"
+	"testing"
+	"time"
+)
+
+func TestStruct(t *testing.T) {
+	name := "test"
+	age := 18
+	enterTime := time.Now().Local()
+
+	studentStruct := NewStruct(
+		StructFieldDefinition{
+			Name: "Name",
+			Type: reflect.TypeOf(""),
+			Tag:  "json:name",
+		},
+		StructFieldDefinition{
+			Name: "Age",
+			Type: reflect.TypeOf(0),
+			Tag:  "json:age",
+		},
+		StructFieldDefinition{
+			Name: "EnterTime",
+			Type: reflect.TypeOf(time.Time{}),
+			Tag:  "json:enterTime",
+		},
+	)
+
+	studentStruct.SetFieldValues(map[string]any{
+		"Name":      name,
+		"Age":       age,
+		"EnterTime": enterTime,
+	})
+
+	values := studentStruct.FieldValues("Name", "Age", "EnterTime")
+
+	for fieldName, value := range values {
+		switch fieldName {
+		case "Name":
+			if value != name {
+				t.Fatalf("%+v\n", errors.Errorf("名字不一致: except: %v, actual: %v", name, value))
+			}
+		case "Age":
+			if value != age {
+				t.Fatalf("%+v\n", errors.Errorf("年龄不一致: except: %v, actual: %v", age, value))
+			}
+		case "EnterTime":
+			if value != enterTime {
+				t.Fatalf("%+v\n", errors.Errorf("入学时间不一致: except: %v, actual: %v", enterTime, value))
+			}
+		default:
+			t.Fatalf("%+v\n", errors.New("不存在的字段"))
+		}
+	}
+
+	studentStruct.MakeMethod(
+		StructMethodDefinition{
+			Name:             "Print",
+			ArgTypes:         []reflect.Type{reflect.TypeOf("")},
+			ReturnValueTypes: []reflect.Type{reflect.TypeOf(errors.New(""))},
+			Body: func(s *Struct, args ...any) []any {
+				values := studentStruct.FieldValues("Name", "Age", "EnterTime")
+
+				fmt.Println("Student Info:")
+				fmt.Println("Name:", values["Name"])
+				fmt.Println("Age:", values["Age"])
+				fmt.Println("EnterTime:", values["EnterTime"].(time.Time).Format(time.DateTime))
+				fmt.Println("Arg:", args[0])
+
+				return []any{nil}
+			},
+		},
+	)
+
+	returns := studentStruct.CallMethod("Print", "Hello Args")
+	if returns[0] != nil {
+		t.Fatalf("%+v\n", errors.Errorf("%v", returns[0]))
+	}
+}
+
+func TestFunction(t *testing.T) {
+	printHelloFunc := MakeFunction(FunctionDefinition{
+		ArgTypes:         []reflect.Type{reflect.TypeOf("")},
+		ReturnValueTypes: []reflect.Type{reflect.TypeOf(errors.New(""))},
+		Body: func(args ...any) []any {
+			fmt.Printf("Hello %v!\n", args[0])
+			return []any{nil}
+		},
+	})
+
+	returns := printHelloFunc.Call("World")
+	if returns[0] != nil {
+		t.Fatalf("%+v\n", errors.Errorf("%v", returns[0]))
+	}
+}

+ 73 - 0
reflectutils/type.go

@@ -0,0 +1,73 @@
+package reflectutils
+
+import "reflect"
+
+// GroupTypeKind 将反射的Kind值进行聚集
+func GroupTypeKind(t reflect.Type) reflect.Kind {
+	kind := t.Kind()
+
+	switch {
+	case kind >= reflect.Int && kind <= reflect.Int64:
+		return reflect.Int64
+	case kind >= reflect.Uint && kind <= reflect.Uint64:
+		return reflect.Uint64
+	case kind >= reflect.Float32 && kind <= reflect.Float64:
+		return reflect.Float64
+	default:
+		return kind
+	}
+}
+
+func PointerTypeElem(t reflect.Type) reflect.Type {
+	elem := t
+	if t.Kind() == reflect.Ptr {
+		elem = t.Elem()
+	}
+
+	return elem
+}
+
+func SliceTypeElem(t reflect.Type) reflect.Type {
+	elem := t
+	if t.Kind() == reflect.Slice {
+		elem = t.Elem()
+	}
+
+	return elem
+}
+
+func IsSliceTypeOf(t reflect.Type, elementKind reflect.Kind) bool {
+	return t.Kind() == reflect.Slice && t.Elem().Kind() == elementKind
+}
+
+func IsTypeInteger(t reflect.Type) bool {
+	return t.Kind() >= reflect.Int && t.Kind() <= reflect.Int64
+}
+
+func IsTypeUnsignedInteger(t reflect.Type) bool {
+	return t.Kind() >= reflect.Uint && t.Kind() <= reflect.Uint64
+}
+
+func IsTypeFloat(t reflect.Type) bool {
+	return t.Kind() >= reflect.Float32 && t.Kind() <= reflect.Float64
+}
+
+func IsTypeStructPointer(t reflect.Type) bool {
+	return t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Struct
+}
+
+func IsTypeStructOrStructPointer(t reflect.Type) bool {
+	return t.Kind() == reflect.Struct || IsTypeStructPointer(t)
+}
+
+func IsTypeStructSliceOrStructSlicePointer(t reflect.Type) bool {
+	return IsSliceTypeOf(t, reflect.Struct) || (t.Kind() == reflect.Pointer && IsSliceTypeOf(t.Elem(), reflect.Struct))
+}
+
+func IsTypeTime(t reflect.Type) bool {
+	return t.Kind() == reflect.Struct && t.String() == "time.Time"
+}
+
+func IsTypeTimePointer(t reflect.Type) bool {
+	return t.Kind() == reflect.Pointer && IsTypeTime(t.Elem())
+}

+ 397 - 0
reflectutils/value.go

@@ -0,0 +1,397 @@
+package reflectutils
+
+import (
+	"github.com/pkg/errors"
+	"reflect"
+	"strconv"
+)
+
+// GroupValueKind 将反射的Kind值进行聚集
+func GroupValueKind(v reflect.Value) reflect.Kind {
+	kind := v.Kind()
+
+	switch {
+	case kind >= reflect.Int && kind <= reflect.Int64:
+		return reflect.Int64
+	case kind >= reflect.Uint && kind <= reflect.Uint64:
+		return reflect.Uint64
+	case kind >= reflect.Float32 && kind <= reflect.Float64:
+		return reflect.Float64
+	default:
+		return kind
+	}
+}
+
+func PointerValueElem(v reflect.Value) reflect.Value {
+	elem := v
+	if v.Kind() == reflect.Ptr {
+		elem = v.Elem()
+	}
+
+	return elem
+}
+
+func SliceValueElem(v reflect.Value) reflect.Value {
+	elem := v
+	if v.Kind() == reflect.Slice {
+		elem = v.Elem()
+	}
+
+	return elem
+}
+
+func IsSliceValueOf(v reflect.Value, elementKind reflect.Kind) bool {
+	return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == elementKind
+}
+
+func IsValueInteger(v reflect.Value) bool {
+	return v.Kind() >= reflect.Int && v.Kind() <= reflect.Int64
+}
+
+func IsValueUnsignedInteger(v reflect.Value) bool {
+	return v.Kind() >= reflect.Uint && v.Kind() <= reflect.Uint64
+}
+
+func IsValueFloat(v reflect.Value) bool {
+	return v.Kind() >= reflect.Float32 && v.Kind() <= reflect.Float64
+}
+
+func IsValueStructPointer(v reflect.Value) bool {
+	return v.Kind() == reflect.Pointer && v.Elem().Kind() == reflect.Struct
+}
+
+func IsValueStructOrStructPointer(v reflect.Value) bool {
+	return v.Kind() == reflect.Struct || IsValueStructPointer(v)
+}
+
+func IsValueStructSliceOrStructSlicePointer(v reflect.Value) bool {
+	return IsSliceValueOf(v, reflect.Struct) || (v.Kind() == reflect.Pointer && IsSliceValueOf(v.Elem(), reflect.Struct))
+}
+
+func IsValueTime(v reflect.Value) bool {
+	return v.Kind() == reflect.Struct && v.Type().String() == "time.Time"
+}
+
+func IsValueTimePointer(v reflect.Value) bool {
+	return v.Kind() == reflect.Pointer && IsValueTime(v.Elem())
+}
+
+// AssignStringValue 将any类型的值进行转化,赋值给string的reflect.Value
+func AssignStringValue(data any, val reflect.Value) error {
+	if data == nil {
+		return nil
+	}
+
+	if val.Kind() != reflect.String {
+		return errors.New("val应当为string类型的Value")
+	}
+
+	v, err := ToString(data)
+	if err != nil {
+		return err
+	}
+
+	val.SetString(v)
+
+	return nil
+}
+
+// AssignInt64Value 将any类型的值进行转化,赋值给int64类型的reflect.Value
+func AssignInt64Value(data any, val reflect.Value) error {
+	if data == nil {
+		return nil
+	}
+
+	if val.Kind() < reflect.Int && val.Kind() > reflect.Int64 {
+		return errors.New("val应当为int类型的Value")
+	}
+
+	v, err := ToInt64(data)
+	if err != nil {
+		return err
+	}
+
+	val.SetInt(v)
+
+	return nil
+}
+
+// AssignUint64Value 将any类型的值进行转化,赋值给uint64类型的reflect.Value
+func AssignUint64Value(data any, val reflect.Value) error {
+	if data == nil {
+		return nil
+	}
+
+	if val.Kind() < reflect.Uint && val.Kind() > reflect.Uint64 {
+		return errors.New("val应当为uint类型的Value")
+	}
+
+	v, err := ToUint64(data)
+	if err != nil {
+		return err
+	}
+
+	val.SetUint(v)
+
+	return nil
+}
+
+// AssignBoolValue 将any类型的值进行转化,赋值给bool类型的reflect.Value
+func AssignBoolValue(data any, val reflect.Value) error {
+	if data == nil {
+		return nil
+	}
+
+	if val.Kind() != reflect.Bool {
+		return errors.New("val应当为bool类型的Value")
+	}
+
+	v, err := ToBool(data)
+	if err != nil {
+		return err
+	}
+
+	val.SetBool(v)
+
+	return nil
+}
+
+// AssignFloat64Value 将any类型的值进行转化,赋值给float64类型的reflect.Value
+func AssignFloat64Value(data any, val reflect.Value) error {
+	if data == nil {
+		return nil
+	}
+
+	if val.Kind() != reflect.Float32 && val.Kind() != reflect.Float64 {
+		return errors.New("val应当为float类型的Value")
+	}
+
+	v, err := ToFloat64(data)
+	if err != nil {
+		return err
+	}
+
+	val.SetFloat(v)
+
+	return nil
+}
+
+// ToString 将any类型的值进行转化为string类型
+func ToString(data any) (string, error) {
+	if data == nil {
+		return "", nil
+	}
+
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	dataKind := GroupValueKind(dataVal)
+
+	switch dataKind {
+	case reflect.String:
+		return dataVal.String(), nil
+	case reflect.Bool:
+		if dataVal.Bool() {
+			return "1", nil
+		} else {
+			return "0", nil
+		}
+	case reflect.Int64:
+		return strconv.FormatInt(dataVal.Int(), 10), nil
+	case reflect.Uint64:
+		return strconv.FormatUint(dataVal.Uint(), 10), nil
+	case reflect.Float64:
+		return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
+	case reflect.Slice, reflect.Array:
+		elemKind := dataVal.Type().Elem().Kind()
+
+		if elemKind != reflect.Uint8 {
+			return "", errors.New("不支持的类型: " + dataVal.Type().String())
+		}
+
+		var uints []uint8
+		if dataKind == reflect.Array {
+			uints = make([]uint8, dataVal.Len(), dataVal.Len())
+			for i := range uints {
+				uints[i] = dataVal.Index(i).Interface().(uint8)
+			}
+		} else {
+			uints = dataVal.Interface().([]uint8)
+		}
+
+		return string(uints), nil
+	default:
+		return "", errors.New("不支持的类型: " + dataVal.Type().String())
+	}
+}
+
+// ToInt64 将any类型的值进行转化为int64类型
+func ToInt64(data any) (int64, error) {
+	if data == nil {
+		return 0, nil
+	}
+
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	dataKind := GroupValueKind(dataVal)
+
+	switch dataKind {
+	case reflect.Int64:
+		return dataVal.Int(), nil
+	case reflect.Uint64:
+		return int64(dataVal.Uint()), nil
+	case reflect.Float64:
+		return int64(dataVal.Float()), nil
+	case reflect.Bool:
+		if dataVal.Bool() {
+			return 1, nil
+		} else {
+			return 0, nil
+		}
+	case reflect.String:
+		str := dataVal.String()
+		if str == "" {
+			str = "0"
+		}
+
+		return strconv.ParseInt(str, 0, 10)
+	default:
+		return 0, errors.New("不支持的类型: " + dataVal.Type().String())
+	}
+}
+
+// ToUint64 将any类型的值进行转化为uint64类型
+func ToUint64(data any) (uint64, error) {
+	if data == nil {
+		return 0, nil
+	}
+
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	dataKind := GroupValueKind(dataVal)
+
+	switch dataKind {
+	case reflect.Int64:
+		return uint64(dataVal.Int()), nil
+	case reflect.Uint64:
+		return dataVal.Uint(), nil
+	case reflect.Float64:
+		return uint64(dataVal.Float()), nil
+	case reflect.Bool:
+		if dataVal.Bool() {
+			return 1, nil
+		} else {
+			return 0, nil
+		}
+	case reflect.String:
+		str := dataVal.String()
+		if str == "" {
+			str = "0"
+		}
+
+		return strconv.ParseUint(str, 0, 10)
+	default:
+		return 0, errors.New("不支持的类型: " + dataVal.Type().String())
+	}
+}
+
+// ToBool 将any类型的值进行转化为bool类型
+func ToBool(data any) (bool, error) {
+	if data == nil {
+		return false, nil
+	}
+
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	dataKind := GroupValueKind(dataVal)
+
+	switch dataKind {
+	case reflect.Bool:
+		return dataVal.Bool(), nil
+	case reflect.Int64:
+		return dataVal.Int() != 0, nil
+	case reflect.Uint64:
+		return dataVal.Uint() != 0, nil
+	case reflect.Float64:
+		return dataVal.Float() != 0, nil
+	case reflect.String:
+		if dataVal.String() == "" {
+			return false, nil
+		} else {
+			return strconv.ParseBool(dataVal.String())
+		}
+	default:
+		return false, errors.New("不支持的类型: " + dataVal.Type().String())
+	}
+}
+
+// ToFloat64 将any类型的值进行转化为float64类型
+func ToFloat64(data any) (float64, error) {
+	if data == nil {
+		return 0, nil
+	}
+
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	dataKind := GroupValueKind(dataVal)
+
+	switch dataKind {
+	case reflect.Int64:
+		return float64(dataVal.Int()), nil
+	case reflect.Uint64:
+		return float64(dataVal.Uint()), nil
+	case reflect.Float64:
+		return dataVal.Float(), nil
+	case reflect.Bool:
+		if dataVal.Bool() {
+			return 1, nil
+		} else {
+			return 0, nil
+		}
+	case reflect.String:
+		str := dataVal.String()
+		if str == "" {
+			str = "0"
+		}
+
+		return strconv.ParseFloat(str, 10)
+	default:
+		return 0, errors.New("不支持的类型: " + dataVal.Type().String())
+	}
+}
+
+func Zero[T any]() T {
+	var zeroT T
+
+	zeroAnyValue := reflect.ValueOf(zeroT)
+	zeroAny := ZeroValueToAny(zeroAnyValue)
+	if zeroAny == nil {
+		return zeroT
+	}
+
+	return zeroAny.(T)
+}
+
+func ZeroValueToAny(v reflect.Value) any {
+	if v.Kind() == reflect.Invalid {
+		return nil
+	}
+
+	zeroValue := reflect.New(v.Type()).Elem()
+	if zeroValue.Kind() != reflect.Pointer {
+		zero(&zeroValue)
+		return zeroValue.Interface()
+	}
+
+	zeroValue.Set(reflect.New(zeroValue.Type().Elem()))
+	elemValue := PointerValueElem(zeroValue)
+	zero(&elemValue)
+
+	return zeroValue.Interface()
+}
+
+func zero(v *reflect.Value) {
+	if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
+		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
+	} else if v.Kind() == reflect.Map {
+		v.Set(reflect.MakeMap(v.Type()))
+	} else if v.Kind() == reflect.Chan {
+		v.Set(reflect.MakeChan(v.Type(), 0))
+	} else {
+		v.Set(reflect.New(v.Type()).Elem())
+	}
+}

+ 27 - 0
slice/slice.go

@@ -45,3 +45,30 @@ func ExtractValue[T any, R any](s []T, addTo func(v T) (R, bool)) []R {
 
 	return retSlice
 }
+
+func ExtractIntersectionValue[T comparable](aList, bList []T) []T {
+	aList = RemoveRepeatElement(aList)
+	bList = RemoveRepeatElement(bList)
+	cList := make([]T, 0)
+
+	tmpMap := make(map[T]int)
+	for _, item := range aList {
+		tmpMap[item] = 0
+	}
+
+	for _, item := range bList {
+		if _, ok := tmpMap[item]; ok {
+			cList = append(cList, item)
+		}
+	}
+
+	return cList
+}
+
+func ExtractUnionValue[T comparable](aList, bList []T) []T {
+	cList := make([]T, 0)
+	cList = append(cList, aList...)
+	cList = append(cList, bList...)
+	cList = RemoveRepeatElement(cList)
+	return cList
+}

+ 325 - 0
websocket/websocket.go

@@ -0,0 +1,325 @@
+package websocket
+
+import (
+	"github.com/olahol/melody"
+	"github.com/pkg/errors"
+	"net/http"
+	"sync"
+	"time"
+)
+
+type HandleConnectFunc func(context map[string]any)
+type HandleDisconnectFunc func(context map[string]any)
+type HandleErrorFunc func(err error, context map[string]any)
+type HandleCloseFunc func(i int, s string, context map[string]any) error
+type HandlePongFunc func(context map[string]any)
+type HandleMessageFunc func(message []byte, context map[string]any)
+type BroadCastFilterCallback func(context map[string]any) bool
+
+var managerInstance *Manager
+
+func Init() {
+	if managerInstance == nil {
+		managerInstance = &Manager{
+			melodyMapMutex: &sync.RWMutex{},
+			melodyMap:      make(map[string]*melody.Melody),
+		}
+	}
+}
+
+func Destroy() {
+	if managerInstance != nil {
+		managerInstance.melodyMapMutex.Lock()
+		defer managerInstance.melodyMapMutex.Unlock()
+
+		for _, melodyInstance := range managerInstance.melodyMap {
+			err := melodyInstance.Close()
+			if err != nil {
+				panic(err)
+			}
+		}
+
+		managerInstance.melodyMap = nil
+		managerInstance = nil
+	}
+
+	managerInstance = nil
+}
+
+func GetInstance() *Manager {
+	return managerInstance
+}
+
+type Manager struct {
+	melodyMapMutex *sync.RWMutex
+	melodyMap      map[string]*melody.Melody
+}
+
+func (m *Manager) RegisterHub(groupID string, opts ...InitOption) {
+	m.melodyMapMutex.Lock()
+	defer m.melodyMapMutex.Unlock()
+
+	_, ok := m.melodyMap[groupID]
+	if ok {
+		return
+	}
+
+	melodyInstance := melody.New()
+
+	options := new(InitOptions)
+	for _, opt := range opts {
+		opt(options)
+	}
+
+	if options.writeWaitSec != 0 {
+		melodyInstance.Config.WriteWait = time.Duration(options.writeWaitSec) * time.Second
+	}
+
+	if options.pongWaitSec != 0 {
+		melodyInstance.Config.PongWait = time.Duration(options.pongWaitSec) * time.Second
+	}
+
+	if options.pingPeriodSec != 0 {
+		melodyInstance.Config.PingPeriod = time.Duration(options.pingPeriodSec) * time.Second
+	}
+
+	if options.maxMessageSize != 0 {
+		melodyInstance.Config.MaxMessageSize = options.maxMessageSize
+	}
+
+	if options.messageBufferSize != 0 {
+		melodyInstance.Config.MessageBufferSize = options.messageBufferSize
+	}
+
+	melodyInstance.Config.ConcurrentMessageHandling = options.concurrentMessageHandling
+
+	melodyInstance.Upgrader.CheckOrigin = func(r *http.Request) bool { return true }
+
+	m.melodyMap[groupID] = melodyInstance
+}
+
+func (m *Manager) UnregisterHub(groupID string) {
+	m.melodyMapMutex.Lock()
+	defer m.melodyMapMutex.Unlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	err := melodyInstance.Close()
+	if err != nil {
+		panic(err)
+	}
+
+	melodyInstance = nil
+
+	delete(m.melodyMap, groupID)
+}
+
+func (m *Manager) HandleConnect(groupID string, handleConnectFunc HandleConnectFunc) {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	melodyInstance.HandleConnect(func(session *melody.Session) {
+		if handleConnectFunc != nil {
+			handleConnectFunc(session.Keys)
+		}
+	})
+}
+
+func (m *Manager) HandleDisconnect(groupID string, handleDisconnectFunc HandleDisconnectFunc) {
+	m.melodyMapMutex.Lock()
+	defer m.melodyMapMutex.Unlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	melodyInstance.HandleDisconnect(func(session *melody.Session) {
+		if handleDisconnectFunc != nil {
+			handleDisconnectFunc(session.Keys)
+		}
+	})
+}
+
+func (m *Manager) HandleError(groupID string, handleErrorFunc HandleErrorFunc) {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	melodyInstance.HandleError(func(session *melody.Session, err error) {
+		if handleErrorFunc != nil {
+			handleErrorFunc(err, session.Keys)
+		}
+	})
+}
+
+func (m *Manager) HandleClose(groupID string, handleCloseFunc HandleCloseFunc) {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	melodyInstance.HandleClose(func(session *melody.Session, i int, s string) error {
+		if handleCloseFunc != nil {
+			err := handleCloseFunc(i, s, session.Keys)
+			if err != nil {
+				return err
+			}
+		}
+
+		return nil
+	})
+}
+
+func (m *Manager) HandlePong(groupID string, handlePongFunc HandlePongFunc) {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return
+	}
+
+	melodyInstance.HandlePong(func(session *melody.Session) {
+		if handlePongFunc != nil {
+			handlePongFunc(session.Keys)
+		}
+	})
+}
+
+func (m *Manager) HandleRequest(groupID string, w http.ResponseWriter, r *http.Request, opts ...ConnectionOption) error {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return errors.New("groupID尚未注册")
+	}
+
+	sessionMap := make(map[string]any)
+
+	for _, opt := range opts {
+		opt(&sessionMap)
+	}
+
+	err := melodyInstance.HandleRequestWithKeys(w, r, sessionMap)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (m *Manager) HandleMessage(groupID string, handleMessageFunc HandleMessageFunc) error {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return errors.New("groupID尚未注册")
+	}
+
+	melodyInstance.HandleMessage(func(session *melody.Session, bytes []byte) {
+		if handleMessageFunc != nil {
+			handleMessageFunc(bytes, session.Keys)
+		}
+	})
+
+	return nil
+}
+
+func (m *Manager) BroadCast(groupID string, msg []byte) error {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return errors.New("groupID尚未注册")
+	}
+
+	return melodyInstance.Broadcast(msg)
+}
+
+func (m *Manager) BroadCastFilter(groupID string, msg []byte, filterCallback BroadCastFilterCallback) error {
+	m.melodyMapMutex.RLock()
+	defer m.melodyMapMutex.RUnlock()
+
+	melodyInstance, ok := m.melodyMap[groupID]
+	if !ok {
+		return errors.New("groupID尚未注册")
+	}
+
+	return melodyInstance.BroadcastFilter(msg, func(session *melody.Session) bool {
+		return filterCallback(session.Keys)
+	})
+}
+
+type InitOption func(*InitOptions)
+
+type InitOptions struct {
+	writeWaitSec              int64
+	pongWaitSec               int64
+	pingPeriodSec             int64
+	maxMessageSize            int64
+	messageBufferSize         int
+	concurrentMessageHandling bool
+}
+
+func InitWithWriteWaitSec(writeWaitSec int64) InitOption {
+	return func(options *InitOptions) {
+		options.writeWaitSec = writeWaitSec
+	}
+}
+
+func InitWithPongWaitSec(pongWaitSec int64) InitOption {
+	return func(options *InitOptions) {
+		options.pongWaitSec = pongWaitSec
+	}
+}
+
+func InitWithPingPeriodSec(pingPeriodSec int64) InitOption {
+	return func(options *InitOptions) {
+		options.pingPeriodSec = pingPeriodSec
+	}
+}
+
+func InitWithMaxMessageSize(maxMessageSize int64) InitOption {
+	return func(options *InitOptions) {
+		options.maxMessageSize = maxMessageSize
+	}
+}
+
+func InitWithMaxMessageBufferSize(messageBufferSize int) InitOption {
+	return func(options *InitOptions) {
+		options.messageBufferSize = messageBufferSize
+	}
+}
+
+func InitWithConcurrentMessageHandling(concurrentMessageHandling bool) InitOption {
+	return func(options *InitOptions) {
+		options.concurrentMessageHandling = concurrentMessageHandling
+	}
+}
+
+type ConnectionOption func(sessionMap *map[string]any)
+
+func WithConnectionContext(context map[string]any) ConnectionOption {
+	return func(sessionMap *map[string]any) {
+		*sessionMap = context
+	}
+}

+ 1 - 1
yaml/yaml_checker/schema_doc.go

@@ -1,7 +1,7 @@
 package yaml_checker
 
 import (
-	"errors"
+	"github.com/pkg/errors"
 	"gopkg.in/yaml.v3"
 	"os"
 )

+ 1 - 1
yaml/yaml_checker/schema_node.go

@@ -1,7 +1,7 @@
 package yaml_checker
 
 import (
-	"errors"
+	"github.com/pkg/errors"
 	"reflect"
 )
 

+ 1 - 1
yaml/yaml_loader/yaml_loader.go

@@ -2,8 +2,8 @@ package yaml_loader
 
 import (
 	"bytes"
-	"errors"
 	"fmt"
+	"github.com/pkg/errors"
 	"gopkg.in/yaml.v3"
 	"io"
 	"os"