Merge branch 'dev' of http://git.legu.cc/liwei_3d/go_dreamfactory into dev
This commit is contained in:
commit
c6a2bf7dd8
14
go.mod
14
go.mod
@ -12,12 +12,9 @@ require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/golang/protobuf v1.5.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/mitchellh/hashstructure v1.1.0
|
||||
github.com/modern-go/reflect2 v1.0.2
|
||||
github.com/nacos-group/nacos-sdk-go v1.0.8
|
||||
github.com/natefinch/lumberjack v2.0.0+incompatible
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/xid v1.3.0
|
||||
@ -31,7 +28,7 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.7
|
||||
github.com/valyala/fastrand v1.1.0
|
||||
go.mongodb.org/mongo-driver v1.5.1
|
||||
go.uber.org/zap v1.21.0
|
||||
go.uber.org/multierr v1.6.0
|
||||
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3
|
||||
google.golang.org/protobuf v1.28.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
@ -39,11 +36,9 @@ require (
|
||||
|
||||
require (
|
||||
github.com/akutz/memconn v0.1.0 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 // indirect
|
||||
github.com/apache/thrift v0.16.0 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/aws/aws-sdk-go v1.34.28 // indirect
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect
|
||||
github.com/cenk/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
@ -54,7 +49,6 @@ require (
|
||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect
|
||||
@ -67,6 +61,7 @@ require (
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.3.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/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
||||
@ -113,7 +108,6 @@ require (
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tinylib/msgp v1.1.6 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
@ -125,7 +119,7 @@ require (
|
||||
go.opentelemetry.io/otel v1.6.3 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.6.3 // indirect
|
||||
go.uber.org/atomic v1.7.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/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
@ -133,8 +127,6 @@ require (
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // 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
|
||||
)
|
||||
|
||||
|
17
go.sum
17
go.sum
@ -44,7 +44,6 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
||||
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=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
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/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw=
|
||||
@ -58,8 +57,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
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/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/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY=
|
||||
@ -83,7 +80,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
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/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/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cenk/backoff v2.2.1+incompatible h1:djdFT7f4gF2ttuzRKPbMOWgZajgesItGLwG5FTQKmmE=
|
||||
github.com/cenk/backoff v2.2.1+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE=
|
||||
@ -146,7 +142,6 @@ github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWp
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -292,7 +287,6 @@ 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.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
@ -385,7 +379,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
|
||||
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
||||
@ -476,8 +469,6 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
||||
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/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/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
@ -495,8 +486,6 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/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/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
|
||||
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/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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
@ -617,10 +606,8 @@ github.com/smallnest/quick v0.0.0-20220103065406-780def6371e6 h1:J8xk0QMMrqfDLqU
|
||||
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/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/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/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
@ -668,7 +655,6 @@ github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw=
|
||||
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk=
|
||||
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
@ -1167,10 +1153,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
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/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"go_dreamfactory/lego/base"
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/core/cbase"
|
||||
"go_dreamfactory/lego/sys/codec"
|
||||
"go_dreamfactory/lego/sys/event"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/sys/rpcx"
|
||||
@ -85,12 +84,6 @@ func (this *RPCXService) InitSys() {
|
||||
} else {
|
||||
log.Infof("Sys event Init success !")
|
||||
}
|
||||
//初始化编码Codec
|
||||
if err := codec.OnInit(this.opts.Setting.Sys["codec"]); err != nil {
|
||||
log.Panicf(fmt.Sprintf("Sys codec Init err:%v", err))
|
||||
} else {
|
||||
log.Infof("Sys codec Init success !")
|
||||
}
|
||||
//初始化rpcx系统
|
||||
if err := rpcx.OnInit(this.opts.Setting.Sys["rpcx"], rpcx.SetServiceTag(this.GetTag()), rpcx.SetServiceId(this.GetId()), rpcx.SetServiceType(this.GetType()), rpcx.SetServiceVersion(this.GetVersion()), rpcx.SetServiceAddr(fmt.Sprintf("%s:%d", this.GetIp(), this.GetPort()))); err != nil {
|
||||
log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err))
|
||||
|
@ -1,134 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
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()
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
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")
|
||||
}
|
||||
}
|
@ -1,820 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
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)
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,273 +0,0 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/sys/codec/factory"
|
||||
"go_dreamfactory/lego/sys/codec/render"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func newSys(options core.Options) (sys *Codec, err error) {
|
||||
sys = &Codec{
|
||||
options: &options,
|
||||
decoderCache: new(sync.Map),
|
||||
encoderCache: new(sync.Map),
|
||||
streamPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return render.NewStream(sys, 512)
|
||||
},
|
||||
},
|
||||
extraPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return render.NewExtractor(sys)
|
||||
},
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Codec struct {
|
||||
options *core.Options
|
||||
decoderCache *sync.Map
|
||||
encoderCache *sync.Map
|
||||
streamPool *sync.Pool
|
||||
extraPool *sync.Pool
|
||||
}
|
||||
|
||||
func (this *Codec) Options() *core.Options {
|
||||
return this.options
|
||||
}
|
||||
|
||||
func (this *Codec) addDecoderToCache(cacheKey uintptr, decoder core.IDecoder) {
|
||||
this.decoderCache.Store(cacheKey, decoder)
|
||||
}
|
||||
func (this *Codec) addEncoderToCache(cacheKey uintptr, encoder core.IEncoder) {
|
||||
this.encoderCache.Store(cacheKey, encoder)
|
||||
}
|
||||
|
||||
func (this *Codec) GetEncoderFromCache(cacheKey uintptr) core.IEncoder {
|
||||
encoder, found := this.encoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return encoder.(core.IEncoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *Codec) GetDecoderFromCache(cacheKey uintptr) core.IDecoder {
|
||||
decoder, found := this.decoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return decoder.(core.IDecoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *Codec) EncoderOf(typ reflect2.Type) core.IEncoder {
|
||||
cacheKey := typ.RType()
|
||||
encoder := this.GetEncoderFromCache(cacheKey)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
ctx := &core.Ctx{
|
||||
ICodec: this,
|
||||
Prefix: "",
|
||||
Decoders: map[reflect2.Type]core.IDecoder{},
|
||||
Encoders: map[reflect2.Type]core.IEncoder{},
|
||||
}
|
||||
encoder = factory.EncoderOfType(ctx, typ)
|
||||
if typ.LikePtr() {
|
||||
encoder = factory.NewonePtrEncoder(encoder)
|
||||
}
|
||||
this.addEncoderToCache(cacheKey, encoder)
|
||||
return encoder
|
||||
}
|
||||
|
||||
func (this *Codec) DecoderOf(typ reflect2.Type) core.IDecoder {
|
||||
cacheKey := typ.RType()
|
||||
decoder := this.GetDecoderFromCache(cacheKey)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
ctx := &core.Ctx{
|
||||
ICodec: this,
|
||||
Prefix: "",
|
||||
Decoders: map[reflect2.Type]core.IDecoder{},
|
||||
Encoders: map[reflect2.Type]core.IEncoder{},
|
||||
}
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
decoder = factory.DecoderOfType(ctx, ptrType.Elem())
|
||||
this.addDecoderToCache(cacheKey, decoder)
|
||||
return decoder
|
||||
}
|
||||
|
||||
func (this *Codec) BorrowStream() core.IStream {
|
||||
stream := this.streamPool.Get().(core.IStream)
|
||||
return stream
|
||||
}
|
||||
|
||||
func (this *Codec) ReturnStream(stream core.IStream) {
|
||||
this.streamPool.Put(stream)
|
||||
}
|
||||
|
||||
func (this *Codec) BorrowExtractor(buf []byte) core.IExtractor {
|
||||
extra := this.extraPool.Get().(core.IExtractor)
|
||||
extra.ResetBytes(buf)
|
||||
return extra
|
||||
}
|
||||
|
||||
func (this *Codec) ReturnExtractor(extra core.IExtractor) {
|
||||
this.extraPool.Put(extra)
|
||||
}
|
||||
|
||||
//编码对象到json
|
||||
func (this *Codec) MarshalJson(val interface{}, option ...core.ExecuteOption) (buf []byte, err error) {
|
||||
stream := this.BorrowStream()
|
||||
defer this.ReturnStream(stream)
|
||||
stream.WriteVal(val)
|
||||
if stream.Error() != nil {
|
||||
return nil, stream.Error()
|
||||
}
|
||||
result := stream.Buffer()
|
||||
copied := make([]byte, len(result))
|
||||
copy(copied, result)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
//解码json到对象
|
||||
func (this *Codec) UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error {
|
||||
extra := this.BorrowExtractor(data)
|
||||
defer this.ReturnExtractor(extra)
|
||||
extra.ReadVal(v)
|
||||
return extra.Error()
|
||||
}
|
||||
|
||||
//编码对象到mapjson
|
||||
func (this *Codec) MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) {
|
||||
if nil == val {
|
||||
err = errors.New("val is null")
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := this.GetEncoderFromCache(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = this.EncoderOf(typ)
|
||||
}
|
||||
if encoderMapJson, ok := encoder.(core.IEncoderMapJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
ret, err = encoderMapJson.EncodeToMapJson(reflect2.PtrOf(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//解码mapjson到对象
|
||||
func (this *Codec) UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) {
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
decoder := this.GetDecoderFromCache(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
if typ == nil || typ.Kind() != reflect.Ptr {
|
||||
err = errors.New("can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = this.DecoderOf(typ)
|
||||
}
|
||||
ptr := reflect2.PtrOf(val)
|
||||
if ptr == nil {
|
||||
err = errors.New("can not read into nil pointer")
|
||||
return
|
||||
}
|
||||
if decoderMapJson, ok := decoder.(core.IDecoderMapJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
err = decoderMapJson.DecodeForMapJson(ptr, data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//编码对象到sliceJson
|
||||
func (this *Codec) MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) {
|
||||
if nil == val {
|
||||
err = errors.New("val is null")
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := this.GetEncoderFromCache(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = this.EncoderOf(typ)
|
||||
}
|
||||
if encoderMapJson, ok := encoder.(core.IEncoderSliceJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
ret, err = encoderMapJson.EncodeToSliceJson(reflect2.PtrOf(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//解码sliceJson到对象
|
||||
func (this *Codec) UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) {
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
decoder := this.GetDecoderFromCache(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
if typ == nil || typ.Kind() != reflect.Ptr {
|
||||
err = errors.New("can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = this.DecoderOf(typ)
|
||||
}
|
||||
ptr := reflect2.PtrOf(val)
|
||||
if ptr == nil {
|
||||
err = errors.New("can not read into nil pointer")
|
||||
return
|
||||
}
|
||||
if decoderMapJson, ok := decoder.(core.IDecoderSliceJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support UnmarshalSliceJson", val)
|
||||
} else {
|
||||
err = decoderMapJson.DecodeForSliceJson(ptr, data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
///日志***********************************************************************
|
||||
func (this *Codec) Debug() bool {
|
||||
return this.options.Debug
|
||||
}
|
||||
|
||||
func (this *Codec) Debugf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Debugf("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Codec) Infof(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Infof("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Codec) Warnf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Warnf("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Codec) Errorf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Errorf("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Codec) Panicf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Panicf("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Codec) Fatalf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Fatalf("[SYS Codec] "+format, a...)
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
type (
|
||||
ISys interface {
|
||||
DecoderOf(typ reflect2.Type) core.IDecoder
|
||||
EncoderOf(typ reflect2.Type) core.IEncoder
|
||||
MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error)
|
||||
UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error
|
||||
MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error)
|
||||
UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error)
|
||||
MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error)
|
||||
UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error)
|
||||
}
|
||||
)
|
||||
|
||||
var defsys ISys
|
||||
|
||||
func OnInit(config map[string]interface{}, option ...core.Option) (err error) {
|
||||
defsys, err = newSys(newOptions(config, option...))
|
||||
return
|
||||
}
|
||||
|
||||
func NewSys(option ...core.Option) (sys ISys, err error) {
|
||||
sys, err = newSys(newOptionsByOption(option...))
|
||||
return
|
||||
}
|
||||
func DecoderOf(typ reflect2.Type) core.IDecoder {
|
||||
return defsys.DecoderOf(typ)
|
||||
}
|
||||
func EncoderOf(typ reflect2.Type) core.IEncoder {
|
||||
return defsys.EncoderOf(typ)
|
||||
}
|
||||
func MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error) {
|
||||
return defsys.MarshalJson(v, option...)
|
||||
}
|
||||
func UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error {
|
||||
return defsys.UnmarshalJson(data, v, option...)
|
||||
}
|
||||
func MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) {
|
||||
return defsys.MarshalMapJson(val, option...)
|
||||
}
|
||||
func UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) {
|
||||
return defsys.UnmarshalMapJson(data, val, option...)
|
||||
}
|
||||
func MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) {
|
||||
return defsys.MarshalSliceJson(val, option...)
|
||||
}
|
||||
func UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) {
|
||||
return defsys.UnmarshalSliceJson(data, val)
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
)
|
||||
|
||||
type Option func(*Options)
|
||||
type Options struct {
|
||||
IndentionStep int //缩进步骤
|
||||
ObjectFieldMustBeSimpleString bool //对象字段必须是简单字符串
|
||||
OnlyTaggedField bool //仅仅处理标签字段
|
||||
DisallowUnknownFields bool //禁止未知字段
|
||||
CaseSensitive bool //是否区分大小写
|
||||
TagKey string //标签
|
||||
Debug bool //日志是否开启
|
||||
Log log.ILog
|
||||
}
|
||||
|
||||
//执行选项
|
||||
type ExecuteOption func(*ExecuteOptions)
|
||||
type ExecuteOptions struct {
|
||||
}
|
||||
|
||||
func NewExecuteOptions(opts ...ExecuteOption) ExecuteOptions {
|
||||
options := ExecuteOptions{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/utils/mapstructure"
|
||||
)
|
||||
|
||||
func newOptions(config map[string]interface{}, opts ...core.Option) core.Options {
|
||||
options := core.Options{
|
||||
IndentionStep: 2,
|
||||
TagKey: "json",
|
||||
}
|
||||
if config != nil {
|
||||
mapstructure.Decode(config, &options)
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if options.Debug && options.Log == nil {
|
||||
options.Log = log.Clone()
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func newOptionsByOption(opts ...core.Option) core.Options {
|
||||
options := core.Options{
|
||||
IndentionStep: 2,
|
||||
TagKey: "json",
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if options.Debug && options.Log == nil {
|
||||
options.Log = log.Clone()
|
||||
}
|
||||
return options
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package render
|
||||
|
||||
import "go_dreamfactory/lego/sys/codec/core"
|
||||
|
||||
const maxDepth = 10000
|
||||
|
||||
var hexDigits []byte
|
||||
var valueTypes []core.ValueType
|
||||
|
||||
func init() {
|
||||
hexDigits = make([]byte, 256)
|
||||
for i := 0; i < len(hexDigits); i++ {
|
||||
hexDigits[i] = 255
|
||||
}
|
||||
for i := '0'; i <= '9'; i++ {
|
||||
hexDigits[i] = byte(i - '0')
|
||||
}
|
||||
for i := 'a'; i <= 'f'; i++ {
|
||||
hexDigits[i] = byte((i - 'a') + 10)
|
||||
}
|
||||
for i := 'A'; i <= 'F'; i++ {
|
||||
hexDigits[i] = byte((i - 'A') + 10)
|
||||
}
|
||||
valueTypes = make([]core.ValueType, 256)
|
||||
for i := 0; i < len(valueTypes); i++ {
|
||||
valueTypes[i] = core.InvalidValue
|
||||
}
|
||||
valueTypes['"'] = core.StringValue
|
||||
valueTypes['-'] = core.NumberValue
|
||||
valueTypes['0'] = core.NumberValue
|
||||
valueTypes['1'] = core.NumberValue
|
||||
valueTypes['2'] = core.NumberValue
|
||||
valueTypes['3'] = core.NumberValue
|
||||
valueTypes['4'] = core.NumberValue
|
||||
valueTypes['5'] = core.NumberValue
|
||||
valueTypes['6'] = core.NumberValue
|
||||
valueTypes['7'] = core.NumberValue
|
||||
valueTypes['8'] = core.NumberValue
|
||||
valueTypes['9'] = core.NumberValue
|
||||
valueTypes['t'] = core.BoolValue
|
||||
valueTypes['f'] = core.BoolValue
|
||||
valueTypes['n'] = core.NilValue
|
||||
valueTypes['['] = core.ArrayValue
|
||||
valueTypes['{'] = core.ObjectValue
|
||||
}
|
@ -1,206 +0,0 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/sys/codec/utils"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func NewStream(codec core.ICodec, bufSize int) *JsonStream {
|
||||
return &JsonStream{
|
||||
codec: codec,
|
||||
buf: make([]byte, 0, bufSize),
|
||||
err: nil,
|
||||
indention: 0,
|
||||
}
|
||||
}
|
||||
|
||||
type JsonStream struct {
|
||||
codec core.ICodec
|
||||
err error
|
||||
buf []byte
|
||||
indention int
|
||||
}
|
||||
|
||||
//写入对象
|
||||
func (this *JsonStream) WriteVal(val interface{}) {
|
||||
if nil == val {
|
||||
this.WriteNil()
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := this.codec.GetEncoderFromCache(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = this.codec.EncoderOf(typ)
|
||||
}
|
||||
encoder.Encode(reflect2.PtrOf(val), this)
|
||||
}
|
||||
|
||||
func (this *JsonStream) WriteNil() {
|
||||
this.writeFourBytes('n', 'u', 'l', 'l')
|
||||
}
|
||||
func (this *JsonStream) WriteEmptyArray() {
|
||||
this.writeTwoBytes('[', ']')
|
||||
}
|
||||
func (this *JsonStream) WriteArrayStart() {
|
||||
this.indention += this.codec.Options().IndentionStep
|
||||
this.writeByte('[')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonStream) WriteArrayEnd() {
|
||||
this.writeIndention(this.codec.Options().IndentionStep)
|
||||
this.indention -= this.codec.Options().IndentionStep
|
||||
this.writeByte(']')
|
||||
}
|
||||
func (this *JsonStream) WriteEmptyObject() {
|
||||
this.writeTwoBytes('{', '}')
|
||||
}
|
||||
func (this *JsonStream) WriteObjectStart() {
|
||||
this.indention += this.codec.Options().IndentionStep
|
||||
this.writeByte('{')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonStream) WriteObjectEnd() {
|
||||
this.writeIndention(this.codec.Options().IndentionStep)
|
||||
this.indention -= this.codec.Options().IndentionStep
|
||||
this.writeByte('}')
|
||||
}
|
||||
func (this *JsonStream) WriteMemberSplit() {
|
||||
this.writeByte(',')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonStream) WriteKVSplit() {
|
||||
this.writeByte(':')
|
||||
}
|
||||
func (this *JsonStream) WriteKeyStart() {
|
||||
this.writeByte('"')
|
||||
}
|
||||
func (this *JsonStream) WriteKeyEnd() {
|
||||
this.writeByte('"')
|
||||
}
|
||||
func (this *JsonStream) WriteObjectFieldName(val string) {
|
||||
this.WriteString(val)
|
||||
if this.indention > 0 {
|
||||
this.writeTwoBytes(':', ' ')
|
||||
} else {
|
||||
this.writeByte(':')
|
||||
}
|
||||
}
|
||||
func (this *JsonStream) WriteBool(val bool) {
|
||||
if val {
|
||||
this.writeTrue()
|
||||
} else {
|
||||
this.writeFalse()
|
||||
}
|
||||
}
|
||||
func (this *JsonStream) WriteInt8(val int8) {
|
||||
utils.WriteInt8ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteInt16(val int16) {
|
||||
utils.WriteInt16ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteInt32(val int32) {
|
||||
utils.WriteInt32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteInt64(val int64) {
|
||||
utils.WriteInt64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteUint8(val uint8) {
|
||||
utils.WriteUint8ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteUint16(val uint16) {
|
||||
utils.WriteUint16ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteUint32(val uint32) {
|
||||
utils.WriteUint32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteUint64(val uint64) {
|
||||
utils.WriteUint64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteFloat32(val float32) {
|
||||
utils.WriteFloat32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteFloat64(val float64) {
|
||||
utils.WriteFloat64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonStream) WriteString(val string) {
|
||||
valLen := len(val)
|
||||
this.buf = append(this.buf, '"')
|
||||
i := 0
|
||||
for ; i < valLen; i++ {
|
||||
c := val[i]
|
||||
if c > 31 && c != '"' && c != '\\' {
|
||||
this.buf = append(this.buf, c)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == valLen {
|
||||
this.buf = append(this.buf, '"')
|
||||
return
|
||||
}
|
||||
utils.WriteStringSlowPath(&this.buf, i, val, valLen)
|
||||
}
|
||||
func (this *JsonStream) WriteBytes(val []byte) {
|
||||
this.buf = append(this.buf, val...)
|
||||
}
|
||||
func (this *JsonStream) Reset(bufSize int) {
|
||||
this.buf = make([]byte, 0, bufSize)
|
||||
this.err = nil
|
||||
this.indention = 0
|
||||
return
|
||||
}
|
||||
func (this *JsonStream) Buffer() []byte {
|
||||
return this.buf
|
||||
}
|
||||
func (this *JsonStream) Error() error {
|
||||
return this.err
|
||||
}
|
||||
func (this *JsonStream) SetErr(err error) {
|
||||
this.err = err
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// WriteTrue write true to stream
|
||||
func (stream *JsonStream) writeTrue() {
|
||||
stream.writeFourBytes('t', 'r', 'u', 'e')
|
||||
}
|
||||
|
||||
// WriteFalse write false to stream
|
||||
func (stream *JsonStream) writeFalse() {
|
||||
stream.writeFiveBytes('f', 'a', 'l', 's', 'e')
|
||||
}
|
||||
|
||||
func (this *JsonStream) writeByte(c byte) {
|
||||
this.buf = append(this.buf, c)
|
||||
}
|
||||
|
||||
func (this *JsonStream) writeTwoBytes(c1 byte, c2 byte) {
|
||||
this.buf = append(this.buf, c1, c2)
|
||||
}
|
||||
|
||||
func (this *JsonStream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3)
|
||||
}
|
||||
|
||||
func (this *JsonStream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3, c4)
|
||||
}
|
||||
|
||||
func (this *JsonStream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3, c4, c5)
|
||||
}
|
||||
|
||||
func (stream *JsonStream) writeIndention(delta int) {
|
||||
if stream.indention == 0 {
|
||||
return
|
||||
}
|
||||
stream.writeByte('\n')
|
||||
toWrite := stream.indention - delta
|
||||
for i := 0; i < toWrite; i++ {
|
||||
stream.buf = append(stream.buf, ' ')
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package codec_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
type TestData struct {
|
||||
Name string
|
||||
Value int
|
||||
Array []interface{}
|
||||
Data map[string]interface{}
|
||||
}
|
||||
type Test1Data struct {
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func Test_sys_slice(t *testing.T) {
|
||||
if err := log.OnInit(nil); err != nil {
|
||||
fmt.Printf("log init err:%v", err)
|
||||
return
|
||||
}
|
||||
if sys, err := codec.NewSys(); err != nil {
|
||||
fmt.Printf("gin init err:%v", err)
|
||||
} else {
|
||||
data := []*Test1Data{{"liwe", 1}, {"liwe2", 2}}
|
||||
d, err := sys.MarshalJson(data)
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data = []*Test1Data{}
|
||||
err = sys.UnmarshalJson(d, &data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
}
|
||||
}
|
||||
func Test_sys_json(t *testing.T) {
|
||||
if err := log.OnInit(nil); err != nil {
|
||||
fmt.Printf("log init err:%v", err)
|
||||
return
|
||||
}
|
||||
if sys, err := codec.NewSys(); err != nil {
|
||||
fmt.Printf("gin init err:%v", err)
|
||||
} else {
|
||||
d, err := sys.MarshalJson(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data := &TestData{}
|
||||
err = sys.UnmarshalJson(d, data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_sys_mapjson(t *testing.T) {
|
||||
if err := log.OnInit(nil); err != nil {
|
||||
fmt.Printf("log init err:%v", err)
|
||||
return
|
||||
}
|
||||
if sys, err := codec.NewSys(); err != nil {
|
||||
fmt.Printf("gin init err:%v", err)
|
||||
} else {
|
||||
m := map[string]interface{}{"liwe": 123, "aasd": "123"}
|
||||
fmt.Printf("codec Marshal m:%s err:%v", m, err)
|
||||
d, err := sys.MarshalMapJson(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data := &TestData{}
|
||||
err = sys.UnmarshalMapJson(d, data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_sys_reflect2(t *testing.T) {
|
||||
data := []*Test1Data{}
|
||||
ptr := reflect2.TypeOf(&data)
|
||||
kind := ptr.Kind()
|
||||
switch kind {
|
||||
case reflect.Interface:
|
||||
return
|
||||
case reflect.Struct:
|
||||
return
|
||||
case reflect.Array:
|
||||
return
|
||||
case reflect.Slice:
|
||||
return
|
||||
case reflect.Map:
|
||||
return
|
||||
case reflect.Ptr:
|
||||
ptrType := ptr.(*reflect2.UnsafePtrType)
|
||||
elemType := ptrType.Elem()
|
||||
kind = elemType.Kind()
|
||||
if kind == reflect.Slice {
|
||||
sliceelem := elemType.(*reflect2.UnsafeSliceType).Elem()
|
||||
sliceelemkind := sliceelem.Kind()
|
||||
if sliceelemkind == reflect.Ptr {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
@ -18,13 +18,21 @@ type ISys interface {
|
||||
|
||||
var defsys ISys
|
||||
|
||||
func OnInit(config map[string]interface{}, option ...Option) (err error) {
|
||||
defsys, err = newSys(newOptions(config, option...))
|
||||
func OnInit(config map[string]interface{}, opt ...Option) (err error) {
|
||||
var option *Options
|
||||
if option, err = newOptions(config, opt...); err != nil {
|
||||
return
|
||||
}
|
||||
defsys, err = newSys(option)
|
||||
return
|
||||
}
|
||||
|
||||
func NewSys(option ...Option) (sys ISys, err error) {
|
||||
sys, err = newSys(newOptionsByOption(option...))
|
||||
func NewSys(opt ...Option) (sys ISys, err error) {
|
||||
var option *Options
|
||||
if option, err = newOptionsByOption(opt...); err != nil {
|
||||
return
|
||||
}
|
||||
sys, err = newSys(option)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"go_dreamfactory/lego/sys/gin/binding"
|
||||
"go_dreamfactory/lego/sys/gin/render"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -30,17 +31,17 @@ const (
|
||||
)
|
||||
const abortIndex int8 = math.MaxInt8 >> 1
|
||||
|
||||
func newContext(sys ISys, engine *Engine, params *Params, skippedNodes *[]skippedNode) *Context {
|
||||
func newContext(log log.ILogger, engine *Engine, params *Params, skippedNodes *[]skippedNode) *Context {
|
||||
return &Context{
|
||||
engine: engine,
|
||||
params: params,
|
||||
skippedNodes: skippedNodes,
|
||||
writermem: ResponseWriter{log: sys},
|
||||
writermem: ResponseWriter{log: log},
|
||||
}
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Sys ISys
|
||||
Log log.ILogger
|
||||
engine *Engine
|
||||
writermem ResponseWriter
|
||||
Request *http.Request
|
||||
@ -351,7 +352,7 @@ func (this *Context) initFormCache() {
|
||||
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.Log.Errorf("error on parse multipart form array: %v", err)
|
||||
}
|
||||
}
|
||||
this.formCache = req.PostForm
|
||||
|
@ -2,8 +2,6 @@ package engine
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
)
|
||||
|
||||
type HandlerFunc func(*Context)
|
||||
@ -25,11 +23,6 @@ type RouteInfo struct {
|
||||
|
||||
type RoutesInfo []RouteInfo
|
||||
|
||||
type ISys interface {
|
||||
log.Ilogf
|
||||
Debug() bool
|
||||
}
|
||||
|
||||
type IRoutes interface {
|
||||
Group(relativePath string, handlers ...HandlerFunc) IRoutes
|
||||
Use(...HandlerFunc) IRoutes
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"go_dreamfactory/lego/sys/gin/render"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/utils/codec"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
@ -33,14 +34,14 @@ var defaultTrustedCIDRs = []*net.IPNet{
|
||||
},
|
||||
}
|
||||
|
||||
func NewEngine(sys ISys) (engine *Engine) {
|
||||
func NewEngine(log log.ILogger) (engine *Engine) {
|
||||
engine = &Engine{
|
||||
RouterGroup: RouterGroup{
|
||||
Handlers: nil,
|
||||
basePath: "/",
|
||||
root: true,
|
||||
},
|
||||
sys: sys,
|
||||
log: log,
|
||||
FuncMap: template.FuncMap{},
|
||||
RedirectTrailingSlash: true,
|
||||
RedirectFixedPath: false,
|
||||
@ -72,7 +73,7 @@ var mimePlain = []string{MIMEPlain}
|
||||
|
||||
type Engine struct {
|
||||
RouterGroup
|
||||
sys ISys
|
||||
log log.ILogger
|
||||
UseRawPath bool
|
||||
/*
|
||||
如果启用,路由器尝试修复当前请求路径,如果没有
|
||||
@ -194,7 +195,7 @@ func (this *Engine) LoadHTMLGlob(pattern string) {
|
||||
right := this.delims.Right
|
||||
templ := template.Must(template.New("").Delims(left, right).Funcs(this.FuncMap).ParseGlob(pattern))
|
||||
|
||||
if this.sys.Debug() {
|
||||
if this.log.Enabled(log.DebugLevel) {
|
||||
this.debugPrintLoadTemplate(templ)
|
||||
this.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: this.FuncMap, Delims: this.delims}
|
||||
return
|
||||
@ -208,7 +209,7 @@ LoadHTMLFiles 加载一段 HTML 文件
|
||||
并将结果与 HTML 渲染器相关联。
|
||||
*/
|
||||
func (this *Engine) LoadHTMLFiles(files ...string) {
|
||||
if this.sys.Debug() {
|
||||
if this.log.Enabled(log.DebugLevel) {
|
||||
this.HTMLRender = render.HTMLDebug{Files: files, FuncMap: this.FuncMap, Delims: this.delims}
|
||||
return
|
||||
}
|
||||
@ -218,7 +219,7 @@ func (this *Engine) LoadHTMLFiles(files ...string) {
|
||||
|
||||
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
|
||||
this.log.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
|
||||
@ -270,10 +271,10 @@ 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() {
|
||||
if this.log.Enabled(log.DebugLevel) {
|
||||
nuHandlers := len(handlers)
|
||||
handlerName := nameOfFunction(handlers.Last())
|
||||
this.sys.Debugf("%s:%s --> %s handlers:%d", method, path, handlerName, nuHandlers)
|
||||
this.log.Debugf("%s:%s --> %s handlers:%d", method, path, handlerName, nuHandlers)
|
||||
}
|
||||
root := this.trees.get(method)
|
||||
if root == nil {
|
||||
@ -406,7 +407,7 @@ func (this *Engine) serveError(c *Context, code int, defaultMessage []byte) {
|
||||
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)
|
||||
this.log.Errorf("[SYS-Gin] cannot write message to writer during serve error: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -447,7 +448,7 @@ func (this *Engine) redirectRequest(c *Context) {
|
||||
if req.Method != http.MethodGet {
|
||||
code = http.StatusTemporaryRedirect
|
||||
}
|
||||
this.sys.Debugf("redirecting request %d: %s --> %s", code, rPath, rURL)
|
||||
this.log.Debugf("redirecting request %d: %s --> %s", code, rPath, rURL)
|
||||
http.Redirect(c.Writer, req, rURL, code)
|
||||
c.writermem.WriteHeaderNow()
|
||||
}
|
||||
@ -490,22 +491,21 @@ func (this *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) {
|
||||
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}
|
||||
return &Context{Log: this.log, 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())
|
||||
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.log.Debugf(format, len(tmpl.Templates()), buf.String())
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ type IResponseWriter interface {
|
||||
}
|
||||
type ResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
log log.Ilogf
|
||||
log log.ILogger
|
||||
size int
|
||||
status int
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import (
|
||||
"go_dreamfactory/lego/sys/gin/middleware/recovery"
|
||||
)
|
||||
|
||||
func newSys(options Options) (sys *Gin, err error) {
|
||||
func newSys(options *Options) (sys *Gin, err error) {
|
||||
sys = &Gin{
|
||||
options: options,
|
||||
}
|
||||
sys.engine = engine.NewEngine(sys)
|
||||
sys.engine = engine.NewEngine(options.Log)
|
||||
///添加基础中间件
|
||||
sys.engine.Use(logger.Logger([]string{}), recovery.Recovery())
|
||||
if options.CertFile != "" && options.KeyFile != "" {
|
||||
@ -28,7 +28,7 @@ func newSys(options Options) (sys *Gin, err error) {
|
||||
}
|
||||
|
||||
type Gin struct {
|
||||
options Options
|
||||
options *Options
|
||||
server *http.Server
|
||||
engine *engine.Engine
|
||||
}
|
||||
@ -36,7 +36,7 @@ type Gin struct {
|
||||
func (this *Gin) Run(listenPort int) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
this.Errorf("Run err:%v", err)
|
||||
this.options.Log.Errorf("Run err:%v", err)
|
||||
}
|
||||
}()
|
||||
// if this.engine.IsUnsafeTrustedProxies() {
|
||||
@ -44,14 +44,14 @@ func (this *Gin) Run(listenPort int) (err error) {
|
||||
// "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.options.Log.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)
|
||||
this.options.Log.Errorln(err)
|
||||
}
|
||||
}()
|
||||
// err = http.ListenAndServe(fmt.Sprintf(":%d", this.options.ListenPort), this.Handler())
|
||||
@ -59,10 +59,10 @@ func (this *Gin) Run(listenPort int) (err error) {
|
||||
}
|
||||
|
||||
func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) {
|
||||
this.Debugf("Listening and serving HTTPS on :%d", listenPort)
|
||||
this.options.Log.Debugf("Listening and serving HTTPS on :%d", listenPort)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
this.Errorf("RunTLS err:%v", err)
|
||||
this.options.Log.Errorln(err)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -76,7 +76,7 @@ func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) {
|
||||
}
|
||||
go func() {
|
||||
if err := this.server.ListenAndServeTLS(certFile, keyFile); err != nil && errors.Is(err, http.ErrServerClosed) {
|
||||
this.Errorf("listen err:%s", err)
|
||||
this.options.Log.Errorln(err)
|
||||
}
|
||||
}()
|
||||
// err = http.ListenAndServeTLS(addr, certFile, keyFile, this.Handler())
|
||||
@ -84,10 +84,10 @@ func (this *Gin) RunTLS(listenPort int, certFile, keyFile string) (err error) {
|
||||
}
|
||||
|
||||
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())
|
||||
this.options.Log.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)
|
||||
this.options.Log.Errorln(err)
|
||||
}
|
||||
|
||||
}()
|
||||
@ -102,7 +102,7 @@ func (this *Gin) RunListener(listener net.Listener) (err error) {
|
||||
|
||||
func (this *Gin) Close() (err error) {
|
||||
if err = this.server.Shutdown(context.Background()); err != nil {
|
||||
this.Errorf("Close err:%v", err)
|
||||
this.options.Log.Errorln(err)
|
||||
}
|
||||
this.server.Close()
|
||||
return
|
||||
@ -154,39 +154,3 @@ func (this *Gin) Static(relativePath string, root string) engine.IRoutes {
|
||||
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...)
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func Logger(SkipPaths []string) engine.HandlerFunc {
|
||||
path = path + "?" + raw
|
||||
}
|
||||
param.Path = path
|
||||
c.Sys.Debugf(fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
|
||||
c.Log.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,
|
||||
|
@ -73,13 +73,10 @@ func CustomRecoveryWithWriter(handle RecoveryFunc) engine.HandlerFunc {
|
||||
}
|
||||
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)
|
||||
c.Log.Errorf("%s\n%s%s", err, headersToStr, reset)
|
||||
} else {
|
||||
c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s%s",
|
||||
timeFormat(time.Now()), err, stack, reset)
|
||||
c.Log.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s",
|
||||
timeFormat(time.Now()), headersToStr, err, stack, reset)
|
||||
}
|
||||
|
||||
if brokenPipe {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package gin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/utils/mapstructure"
|
||||
)
|
||||
@ -11,7 +13,7 @@ type Options struct {
|
||||
CertFile string //tls文件
|
||||
KeyFile string //tls文件
|
||||
Debug bool //日志是否开启
|
||||
Log log.ILog
|
||||
Log log.ILogger
|
||||
}
|
||||
|
||||
func SetListenPort(v int) Option {
|
||||
@ -38,39 +40,47 @@ func SetDebug(v bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func SetLog(v log.ILog) Option {
|
||||
func SetLog(v log.ILogger) Option {
|
||||
return func(o *Options) {
|
||||
o.Log = v
|
||||
}
|
||||
}
|
||||
|
||||
func newOptions(config map[string]interface{}, opts ...Option) Options {
|
||||
options := Options{
|
||||
func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) {
|
||||
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)
|
||||
o(options)
|
||||
}
|
||||
return options
|
||||
|
||||
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.discovery", 2)); options.Log == nil {
|
||||
err = errors.New("log is nil")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func newOptionsByOption(opts ...Option) Options {
|
||||
options := Options{
|
||||
func newOptionsByOption(opts ...Option) (options *Options, err error) {
|
||||
options = &Options{
|
||||
ListenPort: 8080,
|
||||
CertFile: "",
|
||||
KeyFile: "",
|
||||
Debug: true,
|
||||
Log: log.Clone(log.SetLoglayer(2)),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
o(options)
|
||||
}
|
||||
return options
|
||||
|
||||
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.discovery", 2)); options.Log == nil {
|
||||
err = errors.New("log is nil")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func Test_sys(t *testing.T) {
|
||||
if err := log.OnInit(nil); err != nil {
|
||||
if err := log.OnInit(nil, log.SetFileName("test"), log.SetReportCaller(true)); err != nil {
|
||||
fmt.Printf("log init err:%v", err)
|
||||
return
|
||||
}
|
||||
|
12
lego/sys/log/chown.go
Normal file
12
lego/sys/log/chown.go
Normal file
@ -0,0 +1,12 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func chown(_ string, _ os.FileInfo) error {
|
||||
return nil
|
||||
}
|
19
lego/sys/log/chown_linux.go
Normal file
19
lego/sys/log/chown_linux.go
Normal file
@ -0,0 +1,19 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// osChown is a var so we can mock it out during tests.
|
||||
var osChown = os.Chown
|
||||
|
||||
func chown(name string, info os.FileInfo) error {
|
||||
f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
stat := info.Sys().(*syscall.Stat_t)
|
||||
return osChown(name, int(stat.Uid), int(stat.Gid))
|
||||
}
|
@ -1,82 +1,138 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go_dreamfactory/lego/utils/flietools"
|
||||
)
|
||||
var AllLevels = []Loglevel{
|
||||
PanicLevel,
|
||||
FatalLevel,
|
||||
ErrorLevel,
|
||||
WarnLevel,
|
||||
InfoLevel,
|
||||
DebugLevel,
|
||||
}
|
||||
|
||||
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{})
|
||||
Fields []Field
|
||||
Ilogf interface {
|
||||
Debugf(format string, args ...interface{})
|
||||
Infof(format string, args ...interface{})
|
||||
Printf(format string, args ...interface{})
|
||||
Warnf(format string, args ...interface{})
|
||||
Errorf(format string, args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Panicf(format string, args ...interface{})
|
||||
}
|
||||
IlogIn interface {
|
||||
Debugln(args ...interface{})
|
||||
Infoln(args ...interface{})
|
||||
Println(args ...interface{})
|
||||
Warnln(args ...interface{})
|
||||
Errorln(args ...interface{})
|
||||
Fatalln(args ...interface{})
|
||||
Panicln(args ...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)
|
||||
Debug(msg string, args ...Field)
|
||||
Info(msg string, args ...Field)
|
||||
Print(msg string, args ...Field)
|
||||
Warn(msg string, args ...Field)
|
||||
Error(msg string, args ...Field)
|
||||
Fatal(msg string, args ...Field)
|
||||
Panic(msg string, args ...Field)
|
||||
}
|
||||
ILogger interface {
|
||||
SetName(name string)
|
||||
Enabled(lvl Loglevel) bool
|
||||
Ilogf
|
||||
IlogIn
|
||||
ILog
|
||||
}
|
||||
ISys interface {
|
||||
Clone(name string, skip int) ILogger
|
||||
ILogger
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
defsys ILog
|
||||
defsys ISys
|
||||
)
|
||||
|
||||
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...))
|
||||
func OnInit(config map[string]interface{}, opt ...Option) (err error) {
|
||||
var option *Options
|
||||
if option, err = newOptions(config, opt...); err != nil {
|
||||
return
|
||||
}
|
||||
defsys, err = newSys(option)
|
||||
return
|
||||
}
|
||||
|
||||
func Clone(option ...Option) ILog {
|
||||
if defsys != nil {
|
||||
return defsys.Clone(option...)
|
||||
func NewSys(opt ...Option) (sys ISys, err error) {
|
||||
var option *Options
|
||||
if option, err = newOptionsByOption(opt...); err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
sys, err = newSys(option)
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
func Clone(name string, skip int) ILogger {
|
||||
return defsys.Clone(name, skip)
|
||||
}
|
||||
func Debug(msg string, args ...Field) {
|
||||
defsys.Debug(msg, args...)
|
||||
}
|
||||
func Info(msg string, args ...Field) {
|
||||
defsys.Info(msg, args...)
|
||||
}
|
||||
func Warn(msg string, args ...Field) {
|
||||
defsys.Warn(msg, args...)
|
||||
}
|
||||
func Error(msg string, args ...Field) {
|
||||
defsys.Error(msg, args...)
|
||||
}
|
||||
func Fatal(msg string, args ...Field) {
|
||||
defsys.Fatal(msg, args...)
|
||||
}
|
||||
func Panic(msg string, args ...Field) {
|
||||
defsys.Panic(msg, args...)
|
||||
}
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
defsys.Debugf(format, args...)
|
||||
}
|
||||
func Infof(format string, args ...interface{}) {
|
||||
defsys.Infof(format, args...)
|
||||
}
|
||||
func Warnf(format string, args ...interface{}) {
|
||||
defsys.Warnf(format, args...)
|
||||
}
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
defsys.Errorf(format, args...)
|
||||
}
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
defsys.Fatalf(format, args...)
|
||||
}
|
||||
func Panicf(format string, args ...interface{}) {
|
||||
defsys.Panicf(format, args...)
|
||||
}
|
||||
func Debugln(args ...interface{}) {
|
||||
defsys.Debugln(args...)
|
||||
}
|
||||
func Infoln(args ...interface{}) {
|
||||
defsys.Infoln(args...)
|
||||
}
|
||||
func Println(args ...interface{}) {
|
||||
defsys.Println(args...)
|
||||
}
|
||||
func Warnln(args ...interface{}) {
|
||||
defsys.Warnln(args...)
|
||||
}
|
||||
func Errorln(args ...interface{}) {
|
||||
defsys.Errorln(args...)
|
||||
}
|
||||
func Fatalln(args ...interface{}) {
|
||||
defsys.Fatalln(args...)
|
||||
}
|
||||
func Panicln(args ...interface{}) {
|
||||
defsys.Panicln(args...)
|
||||
}
|
||||
|
116
lego/sys/log/entry.go
Normal file
116
lego/sys/log/entry.go
Normal file
@ -0,0 +1,116 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/utils/pools"
|
||||
)
|
||||
|
||||
var (
|
||||
_cePool = sync.Pool{New: func() interface{} {
|
||||
// Pre-allocate some space for cores.
|
||||
return &Entry{
|
||||
Data: make(Fields, 0, 6),
|
||||
}
|
||||
}}
|
||||
)
|
||||
|
||||
func getEntry() *Entry {
|
||||
return _cePool.Get().(*Entry)
|
||||
}
|
||||
func putEntry(e *Entry) {
|
||||
e.reset()
|
||||
_cePool.Put(e)
|
||||
}
|
||||
|
||||
//日志堆栈信息
|
||||
type EntryCaller struct {
|
||||
Defined bool
|
||||
PC uintptr
|
||||
File string
|
||||
Line int
|
||||
Function string
|
||||
Stack string
|
||||
}
|
||||
|
||||
func (ec EntryCaller) String() string {
|
||||
return ec.FullPath()
|
||||
}
|
||||
func (ec EntryCaller) FullPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
buf := pools.BufferPoolGet()
|
||||
buf.AppendString(ec.File)
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
caller := buf.String()
|
||||
buf.Free()
|
||||
return caller
|
||||
}
|
||||
func (ec EntryCaller) TrimmedPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
idx := strings.LastIndexByte(ec.File, '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
idx = strings.LastIndexByte(ec.File[:idx], '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
buf := pools.BufferPoolGet()
|
||||
buf.AppendString(ec.File[idx+1:])
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
caller := buf.String()
|
||||
buf.Free()
|
||||
return caller
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
Name string
|
||||
Level Loglevel
|
||||
Caller EntryCaller
|
||||
Time time.Time
|
||||
Message string
|
||||
Data Fields
|
||||
Err string
|
||||
}
|
||||
|
||||
func (entry *Entry) reset() {
|
||||
entry.Message = ""
|
||||
entry.Err = ""
|
||||
entry.Data = entry.Data[:0]
|
||||
}
|
||||
|
||||
func (entry *Entry) WithFields(fields ...Field) {
|
||||
if cap(entry.Data) < len(fields) {
|
||||
entry.Data = make(Fields, 0, cap(entry.Data)+len(fields))
|
||||
}
|
||||
fieldErr := entry.Err
|
||||
for _, v := range fields {
|
||||
isErrField := false
|
||||
if t := reflect.TypeOf(v.Value); t != nil {
|
||||
switch {
|
||||
case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
|
||||
isErrField = true
|
||||
}
|
||||
}
|
||||
if isErrField {
|
||||
tmp := fmt.Sprintf("can not add field %q", v.Key)
|
||||
if fieldErr != "" {
|
||||
fieldErr = entry.Err + ", " + tmp
|
||||
} else {
|
||||
fieldErr = tmp
|
||||
}
|
||||
} else {
|
||||
entry.Data = append(entry.Data, v)
|
||||
}
|
||||
}
|
||||
}
|
391
lego/sys/log/flieout.go
Normal file
391
lego/sys/log/flieout.go
Normal file
@ -0,0 +1,391 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
backupTimeFormat = "2006-01-02T15-04-05.000"
|
||||
compressSuffix = ".gz"
|
||||
defaultMaxSize = 100
|
||||
)
|
||||
|
||||
var (
|
||||
currentTime = time.Now
|
||||
osStat = os.Stat
|
||||
megabyte = 1024 * 1024
|
||||
)
|
||||
|
||||
//日志文件输出
|
||||
type LogFileOut struct {
|
||||
Filename string `json:"filename" yaml:"filename"` //日志文件名称
|
||||
MaxSize int `json:"maxsize" yaml:"maxsize"` //日志文件的大小
|
||||
CupTime time.Duration `json:"cuptime" yaml:"cuptime"` //日志切割间隔时间
|
||||
MaxAge int `json:"maxage" yaml:"maxage"` //日志的最大备份天数
|
||||
MaxBackups int `json:"maxbackups" yaml:"maxbackups"` //备份日志的最大数量
|
||||
LocalTime bool `json:"localtime" yaml:"localtime"` //是使用本地时间还是使用世界标准时间
|
||||
Compress bool `json:"compress" yaml:"compress"` //是否压缩备份日志
|
||||
size int64
|
||||
ctime time.Time
|
||||
file *os.File
|
||||
mu sync.Mutex
|
||||
millCh chan bool
|
||||
startMill sync.Once
|
||||
}
|
||||
|
||||
func (l *LogFileOut) filename() string {
|
||||
if l.Filename != "" {
|
||||
return l.Filename
|
||||
}
|
||||
name := filepath.Base(os.Args[0]) + "-lumberjack.log"
|
||||
return filepath.Join(os.TempDir(), name)
|
||||
}
|
||||
func (l *LogFileOut) dir() string {
|
||||
return filepath.Dir(l.filename())
|
||||
}
|
||||
|
||||
func (l *LogFileOut) max() int64 {
|
||||
if l.MaxSize == 0 {
|
||||
return int64(defaultMaxSize * megabyte)
|
||||
}
|
||||
return int64(l.MaxSize) * int64(megabyte)
|
||||
}
|
||||
func (l *LogFileOut) Write(p []byte) (n int, err error) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
writeLen := int64(len(p))
|
||||
if writeLen > l.max() {
|
||||
return 0, fmt.Errorf(
|
||||
"write length %d exceeds maximum file size %d", writeLen, l.max(),
|
||||
)
|
||||
}
|
||||
if l.file == nil {
|
||||
if err = l.openExistingOrNew(len(p)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
n, err = l.file.Write(p)
|
||||
l.size += int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (l *LogFileOut) openExistingOrNew(writeLen int) error {
|
||||
l.mill()
|
||||
|
||||
filename := l.filename()
|
||||
info, err := osStat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return l.openNew()
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting log file info: %s", err)
|
||||
}
|
||||
|
||||
//校验是否需要切割日志
|
||||
if info.Size()+int64(writeLen) >= l.max() || time.Since(l.ctime) > l.CupTime {
|
||||
return l.rotate()
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
// if we fail to open the old log file for some reason, just ignore
|
||||
// it and open a new log file.
|
||||
return l.openNew()
|
||||
}
|
||||
l.file = file
|
||||
l.size = info.Size()
|
||||
return nil
|
||||
}
|
||||
|
||||
//日志切割
|
||||
func (l *LogFileOut) rotate() error {
|
||||
if err := l.close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := l.openNew(); err != nil {
|
||||
return err
|
||||
}
|
||||
l.mill()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LogFileOut) millRunOnce() error {
|
||||
if l.MaxBackups == 0 && l.MaxAge == 0 && !l.Compress {
|
||||
return nil
|
||||
}
|
||||
|
||||
files, err := l.oldLogFiles()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var compress, remove []logInfo
|
||||
|
||||
if l.MaxBackups > 0 && l.MaxBackups < len(files) {
|
||||
preserved := make(map[string]bool)
|
||||
var remaining []logInfo
|
||||
for _, f := range files {
|
||||
// Only count the uncompressed log file or the
|
||||
// compressed log file, not both.
|
||||
fn := f.Name()
|
||||
if strings.HasSuffix(fn, compressSuffix) {
|
||||
fn = fn[:len(fn)-len(compressSuffix)]
|
||||
}
|
||||
preserved[fn] = true
|
||||
|
||||
if len(preserved) > l.MaxBackups {
|
||||
remove = append(remove, f)
|
||||
} else {
|
||||
remaining = append(remaining, f)
|
||||
}
|
||||
}
|
||||
files = remaining
|
||||
}
|
||||
if l.MaxAge > 0 {
|
||||
diff := time.Duration(int64(24*time.Hour) * int64(l.MaxAge))
|
||||
cutoff := currentTime().Add(-1 * diff)
|
||||
|
||||
var remaining []logInfo
|
||||
for _, f := range files {
|
||||
if f.timestamp.Before(cutoff) {
|
||||
remove = append(remove, f)
|
||||
} else {
|
||||
remaining = append(remaining, f)
|
||||
}
|
||||
}
|
||||
files = remaining
|
||||
}
|
||||
|
||||
if l.Compress {
|
||||
for _, f := range files {
|
||||
if !strings.HasSuffix(f.Name(), compressSuffix) {
|
||||
compress = append(compress, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range remove {
|
||||
errRemove := os.Remove(filepath.Join(l.dir(), f.Name()))
|
||||
if err == nil && errRemove != nil {
|
||||
err = errRemove
|
||||
}
|
||||
}
|
||||
for _, f := range compress {
|
||||
fn := filepath.Join(l.dir(), f.Name())
|
||||
errCompress := compressLogFile(fn, fn+compressSuffix)
|
||||
if err == nil && errCompress != nil {
|
||||
err = errCompress
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
func (l *LogFileOut) millRun() {
|
||||
for range l.millCh {
|
||||
// what am I going to do, log this?
|
||||
_ = l.millRunOnce()
|
||||
}
|
||||
}
|
||||
|
||||
//触发日志备份管理
|
||||
func (l *LogFileOut) mill() {
|
||||
l.startMill.Do(func() {
|
||||
l.millCh = make(chan bool, 1)
|
||||
go l.millRun()
|
||||
})
|
||||
select {
|
||||
case l.millCh <- true:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
//备份老的日志文件创建新的日志文件
|
||||
func (l *LogFileOut) openNew() error {
|
||||
err := os.MkdirAll(l.dir(), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't make directories for new logfile: %s", err)
|
||||
}
|
||||
|
||||
name := l.filename()
|
||||
mode := os.FileMode(0600)
|
||||
info, err := osStat(name)
|
||||
//备份老的日志文件
|
||||
if err == nil {
|
||||
// Copy the mode off the old logfile.
|
||||
mode = info.Mode()
|
||||
// move the existing file
|
||||
newname := backupName(name, l.LocalTime)
|
||||
if err := os.Rename(name, newname); err != nil {
|
||||
return fmt.Errorf("can't rename log file: %s", err)
|
||||
}
|
||||
|
||||
// this is a no-op anywhere but linux
|
||||
if err := chown(name, info); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//创建新的日志文件
|
||||
f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't open new logfile: %s", err)
|
||||
}
|
||||
l.file = f
|
||||
l.size = 0
|
||||
l.ctime = currentTime()
|
||||
return nil
|
||||
}
|
||||
|
||||
//关闭当前日志文件
|
||||
func (l *LogFileOut) close() error {
|
||||
if l.file == nil {
|
||||
return nil
|
||||
}
|
||||
err := l.file.Close()
|
||||
l.file = nil
|
||||
return err
|
||||
}
|
||||
|
||||
//获取备份的日子文件集合
|
||||
func (l *LogFileOut) oldLogFiles() ([]logInfo, error) {
|
||||
files, err := ioutil.ReadDir(l.dir())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't read log file directory: %s", err)
|
||||
}
|
||||
logFiles := []logInfo{}
|
||||
|
||||
prefix, ext := l.prefixAndExt()
|
||||
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
if t, err := l.timeFromName(f.Name(), prefix, ext); err == nil {
|
||||
logFiles = append(logFiles, logInfo{t, f})
|
||||
continue
|
||||
}
|
||||
if t, err := l.timeFromName(f.Name(), prefix, ext+compressSuffix); err == nil {
|
||||
logFiles = append(logFiles, logInfo{t, f})
|
||||
continue
|
||||
}
|
||||
// error parsing means that the suffix at the end was not generated
|
||||
// by lumberjack, and therefore it's not a backup file.
|
||||
}
|
||||
|
||||
sort.Sort(byFormatTime(logFiles))
|
||||
|
||||
return logFiles, nil
|
||||
}
|
||||
func (l *LogFileOut) prefixAndExt() (prefix, ext string) {
|
||||
filename := filepath.Base(l.filename())
|
||||
ext = filepath.Ext(filename)
|
||||
prefix = filename[:len(filename)-len(ext)] + "-"
|
||||
return prefix, ext
|
||||
}
|
||||
func (l *LogFileOut) timeFromName(filename, prefix, ext string) (time.Time, error) {
|
||||
if !strings.HasPrefix(filename, prefix) {
|
||||
return time.Time{}, errors.New("mismatched prefix")
|
||||
}
|
||||
if !strings.HasSuffix(filename, ext) {
|
||||
return time.Time{}, errors.New("mismatched extension")
|
||||
}
|
||||
ts := filename[len(prefix) : len(filename)-len(ext)]
|
||||
return time.Parse(backupTimeFormat, ts)
|
||||
}
|
||||
|
||||
//日志备份名
|
||||
func backupName(name string, local bool) string {
|
||||
dir := filepath.Dir(name)
|
||||
filename := filepath.Base(name)
|
||||
ext := filepath.Ext(filename)
|
||||
prefix := filename[:len(filename)-len(ext)]
|
||||
t := currentTime()
|
||||
if !local {
|
||||
t = t.UTC()
|
||||
}
|
||||
|
||||
timestamp := t.Format(backupTimeFormat)
|
||||
return filepath.Join(dir, fmt.Sprintf("%s-%s%s", prefix, timestamp, ext))
|
||||
}
|
||||
|
||||
//压缩日志文件
|
||||
func compressLogFile(src, dst string) (err error) {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open log file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, err := osStat(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stat log file: %v", err)
|
||||
}
|
||||
|
||||
if err := chown(dst, fi); err != nil {
|
||||
return fmt.Errorf("failed to chown compressed log file: %v", err)
|
||||
}
|
||||
|
||||
// If this file already exists, we presume it was created by
|
||||
// a previous attempt to compress the log file.
|
||||
gzf, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open compressed log file: %v", err)
|
||||
}
|
||||
defer gzf.Close()
|
||||
|
||||
gz := gzip.NewWriter(gzf)
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.Remove(dst)
|
||||
err = fmt.Errorf("failed to compress log file: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(gz, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gz.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gzf.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type logInfo struct {
|
||||
timestamp time.Time
|
||||
os.FileInfo
|
||||
}
|
||||
type byFormatTime []logInfo
|
||||
|
||||
func (b byFormatTime) Less(i, j int) bool {
|
||||
return b[i].timestamp.After(b[j].timestamp)
|
||||
}
|
||||
|
||||
func (b byFormatTime) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
func (b byFormatTime) Len() int {
|
||||
return len(b)
|
||||
}
|
70
lego/sys/log/formatter.go
Normal file
70
lego/sys/log/formatter.go
Normal file
@ -0,0 +1,70 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/utils/pools"
|
||||
)
|
||||
|
||||
var _fieldsPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make(Fields, 0, 6)
|
||||
},
|
||||
}
|
||||
|
||||
func getFields() Fields {
|
||||
return _fieldsPool.Get().(Fields)
|
||||
}
|
||||
|
||||
func putFields(fields Fields) {
|
||||
fields = fields[:0]
|
||||
_fieldsPool.Put(fields)
|
||||
}
|
||||
|
||||
func NewDefEncoderConfig() *EncoderConfig {
|
||||
return &EncoderConfig{
|
||||
TimeKey: "ts",
|
||||
LevelKey: "level",
|
||||
CallerKey: "caller",
|
||||
MessageKey: "msg",
|
||||
StacktraceKey: "stacktrace",
|
||||
ConsoleSeparator: "\t",
|
||||
EncodeTime: DefTimeEncoder,
|
||||
EncodeLevel: LowercaseLevelEncoder,
|
||||
EncodeCaller: ShortCallerEncoder,
|
||||
}
|
||||
}
|
||||
|
||||
type TimeEncoder func(time.Time) string
|
||||
type LevelEncoder func(Loglevel) string
|
||||
type CallerEncoder func(EntryCaller) string
|
||||
|
||||
func DefTimeEncoder(t time.Time) string {
|
||||
return t.Format("2006/01/02 15:04:05.000")
|
||||
}
|
||||
|
||||
func LowercaseLevelEncoder(l Loglevel) string {
|
||||
return l.CapitalString()
|
||||
}
|
||||
|
||||
func ShortCallerEncoder(caller EntryCaller) string {
|
||||
return caller.TrimmedPath()
|
||||
}
|
||||
|
||||
type EncoderConfig struct {
|
||||
MessageKey string `json:"messageKey" yaml:"messageKey"`
|
||||
LevelKey string `json:"levelKey" yaml:"levelKey"`
|
||||
TimeKey string `json:"timeKey" yaml:"timeKey"`
|
||||
CallerKey string `json:"callerKey" yaml:"callerKey"`
|
||||
FunctionKey string `json:"functionKey" yaml:"functionKey"`
|
||||
StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
|
||||
ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
|
||||
EncodeTime TimeEncoder
|
||||
EncodeLevel LevelEncoder
|
||||
EncodeCaller CallerEncoder
|
||||
}
|
||||
|
||||
type Formatter interface {
|
||||
Format(config *EncoderConfig, entry *Entry) (*pools.Buffer, error)
|
||||
}
|
144
lego/sys/log/formatter_console.go
Normal file
144
lego/sys/log/formatter_console.go
Normal file
@ -0,0 +1,144 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/utils/pools"
|
||||
)
|
||||
|
||||
func NewConsoleEncoder() Formatter {
|
||||
return &ConsoleFormatter{}
|
||||
}
|
||||
|
||||
type ConsoleFormatter struct {
|
||||
*EncoderConfig
|
||||
}
|
||||
|
||||
func (this *ConsoleFormatter) Format(config *EncoderConfig, entry *Entry) (*pools.Buffer, error) {
|
||||
line := pools.BufferPoolGet()
|
||||
isfirst := true
|
||||
if config.TimeKey != "" && config.EncodeTime != nil {
|
||||
line.AppendString(config.EncodeTime(entry.Time))
|
||||
isfirst = false
|
||||
}
|
||||
if config.LevelKey != "" && config.EncodeLevel != nil {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString(config.EncodeLevel(entry.Level))
|
||||
}
|
||||
if entry.Caller.Defined {
|
||||
if config.CallerKey != "" && config.EncodeCaller != nil {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString(config.EncodeCaller(entry.Caller))
|
||||
}
|
||||
if config.FunctionKey != "" {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString(entry.Caller.Function)
|
||||
}
|
||||
}
|
||||
if entry.Name != "" {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString("[")
|
||||
line.AppendString(entry.Name)
|
||||
line.AppendString("]")
|
||||
}
|
||||
|
||||
if config.MessageKey != "" {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString(entry.Message)
|
||||
}
|
||||
for _, v := range entry.Data {
|
||||
if !isfirst {
|
||||
line.AppendString(config.ConsoleSeparator)
|
||||
}
|
||||
isfirst = false
|
||||
line.AppendString(v.Key)
|
||||
line.AppendString(":")
|
||||
writetoline(line, v.Value)
|
||||
}
|
||||
|
||||
if entry.Caller.Stack != "" && config.StacktraceKey != "" {
|
||||
line.AppendString("\n")
|
||||
line.AppendString(entry.Caller.Stack)
|
||||
}
|
||||
line.AppendString("\n")
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func writetoline(line *pools.Buffer, v interface{}) {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
line.AppendString("nil")
|
||||
break
|
||||
case string:
|
||||
line.AppendString(v)
|
||||
break
|
||||
case []byte:
|
||||
line.AppendBytes(v)
|
||||
break
|
||||
case int:
|
||||
line.AppendInt(int64(v))
|
||||
break
|
||||
case int8:
|
||||
line.AppendInt(int64(v))
|
||||
break
|
||||
case int16:
|
||||
line.AppendInt(int64(v))
|
||||
break
|
||||
case int32:
|
||||
line.AppendInt(int64(v))
|
||||
break
|
||||
case int64:
|
||||
line.AppendInt(int64(v))
|
||||
break
|
||||
case uint:
|
||||
line.AppendUint(uint64(v))
|
||||
break
|
||||
case uint8:
|
||||
line.AppendUint(uint64(v))
|
||||
break
|
||||
case uint16:
|
||||
line.AppendUint(uint64(v))
|
||||
break
|
||||
case uint32:
|
||||
line.AppendUint(uint64(v))
|
||||
break
|
||||
case uint64:
|
||||
line.AppendUint(uint64(v))
|
||||
break
|
||||
case float32:
|
||||
line.AppendFloat(float64(v), 64)
|
||||
break
|
||||
case float64:
|
||||
line.AppendFloat(v, 64)
|
||||
break
|
||||
case bool:
|
||||
line.AppendBool(v)
|
||||
break
|
||||
case time.Time:
|
||||
line.AppendTime(v, time.RFC3339Nano)
|
||||
break
|
||||
case time.Duration:
|
||||
line.AppendInt(v.Nanoseconds())
|
||||
break
|
||||
default:
|
||||
d, _ := json.Marshal(v)
|
||||
line.AppendBytes(d)
|
||||
break
|
||||
}
|
||||
}
|
59
lego/sys/log/level.go
Normal file
59
lego/sys/log/level.go
Normal file
@ -0,0 +1,59 @@
|
||||
package log
|
||||
|
||||
import "fmt"
|
||||
|
||||
type LevelEnabler interface {
|
||||
Enabled(Loglevel) bool
|
||||
}
|
||||
|
||||
type Loglevel int8
|
||||
|
||||
const (
|
||||
PanicLevel Loglevel = iota
|
||||
FatalLevel
|
||||
ErrorLevel
|
||||
WarnLevel
|
||||
InfoLevel
|
||||
DebugLevel
|
||||
)
|
||||
|
||||
func (l Loglevel) String() string {
|
||||
switch l {
|
||||
case DebugLevel:
|
||||
return "debug"
|
||||
case InfoLevel:
|
||||
return "info"
|
||||
case WarnLevel:
|
||||
return "warn"
|
||||
case ErrorLevel:
|
||||
return "error"
|
||||
case PanicLevel:
|
||||
return "panic"
|
||||
case FatalLevel:
|
||||
return "fatal"
|
||||
default:
|
||||
return fmt.Sprintf("Level(%d)", l)
|
||||
}
|
||||
}
|
||||
func (l Loglevel) CapitalString() string {
|
||||
switch l {
|
||||
case DebugLevel:
|
||||
return "DEBUG"
|
||||
case InfoLevel:
|
||||
return "INFO"
|
||||
case WarnLevel:
|
||||
return "WARN"
|
||||
case ErrorLevel:
|
||||
return "ERROR"
|
||||
case PanicLevel:
|
||||
return "PANIC"
|
||||
case FatalLevel:
|
||||
return "FATAL"
|
||||
default:
|
||||
return fmt.Sprintf("LEVEL(%d)", l)
|
||||
}
|
||||
}
|
||||
|
||||
func (l Loglevel) Enabled(lvl Loglevel) bool {
|
||||
return lvl <= l
|
||||
}
|
231
lego/sys/log/logger.go
Normal file
231
lego/sys/log/logger.go
Normal file
@ -0,0 +1,231 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/utils/pools"
|
||||
)
|
||||
|
||||
func newSys(options *Options) (sys *Logger, err error) {
|
||||
hook := LogFileOut{
|
||||
Filename: options.FileName, //日志文件路径
|
||||
MaxAge: options.MaxAgeTime, //备份日志保存天数
|
||||
CupTime: time.Duration(options.CupTimeTime) * time.Hour, //日志切割间隔时间
|
||||
Compress: options.Compress, //是否压缩 disabled by default
|
||||
MaxBackups: options.MaxBackups, //最大备份数
|
||||
LocalTime: true, //使用本地时间
|
||||
}
|
||||
if err = hook.openNew(); err != nil {
|
||||
return
|
||||
}
|
||||
out := make(writeTree, 0, 2)
|
||||
out = append(out, AddSync(&hook))
|
||||
if options.IsDebug {
|
||||
out = append(out, Lock(os.Stdout))
|
||||
}
|
||||
sys = &Logger{
|
||||
config: NewDefEncoderConfig(),
|
||||
formatter: NewConsoleEncoder(),
|
||||
out: out,
|
||||
level: options.Loglevel,
|
||||
addCaller: options.ReportCaller,
|
||||
callerSkip: options.CallerSkip,
|
||||
addStack: FatalLevel,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Logger struct {
|
||||
config *EncoderConfig //编码配置
|
||||
level LevelEnabler //日志输出级别
|
||||
formatter Formatter //日志格式化
|
||||
name string //日志标签
|
||||
out IWrite //日志输出
|
||||
addCaller bool //是否打印堆栈信息
|
||||
addStack LevelEnabler //堆栈信息输出级别
|
||||
callerSkip int //堆栈输出深度
|
||||
}
|
||||
|
||||
func (this *Logger) Clone(name string, skip int) ILogger {
|
||||
return &Logger{
|
||||
config: this.config,
|
||||
formatter: this.formatter,
|
||||
name: name,
|
||||
out: this.out,
|
||||
level: this.level,
|
||||
addCaller: this.addCaller,
|
||||
callerSkip: skip,
|
||||
addStack: this.addStack,
|
||||
}
|
||||
}
|
||||
func (this *Logger) SetName(name string) {
|
||||
this.name = name
|
||||
}
|
||||
func (this *Logger) Enabled(lvl Loglevel) bool {
|
||||
return this.level.Enabled(lvl)
|
||||
}
|
||||
func (this *Logger) Debug(msg string, args ...Field) {
|
||||
this.Log(DebugLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Info(msg string, args ...Field) {
|
||||
this.Log(InfoLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Print(msg string, args ...Field) {
|
||||
this.Log(InfoLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Warn(msg string, args ...Field) {
|
||||
this.Log(WarnLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Error(msg string, args ...Field) {
|
||||
this.Log(ErrorLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Panic(msg string, args ...Field) {
|
||||
this.Log(PanicLevel, msg, args...)
|
||||
}
|
||||
func (this *Logger) Fatal(msg string, args ...Field) {
|
||||
this.Log(FatalLevel, msg, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
func (this *Logger) Log(level Loglevel, msg string, args ...Field) {
|
||||
if this.level.Enabled(level) {
|
||||
this.log(level, msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Logger) Debugf(format string, args ...interface{}) {
|
||||
this.Logf(DebugLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Infof(format string, args ...interface{}) {
|
||||
this.Logf(InfoLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Printf(format string, args ...interface{}) {
|
||||
this.Logf(InfoLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Warnf(format string, args ...interface{}) {
|
||||
this.Logf(WarnLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Errorf(format string, args ...interface{}) {
|
||||
this.Logf(ErrorLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Fatalf(format string, args ...interface{}) {
|
||||
this.Logf(FatalLevel, format, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
func (this *Logger) Panicf(format string, args ...interface{}) {
|
||||
this.Logf(PanicLevel, format, args...)
|
||||
}
|
||||
func (this *Logger) Logf(level Loglevel, format string, args ...interface{}) {
|
||||
if this.level.Enabled(level) {
|
||||
this.log(level, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
func (this *Logger) Debugln(args ...interface{}) {
|
||||
this.Logln(DebugLevel, args...)
|
||||
}
|
||||
func (this *Logger) Infoln(args ...interface{}) {
|
||||
this.Logln(InfoLevel, args...)
|
||||
}
|
||||
func (this *Logger) Println(args ...interface{}) {
|
||||
this.Logln(InfoLevel, args...)
|
||||
}
|
||||
func (this *Logger) Warnln(args ...interface{}) {
|
||||
this.Logln(WarnLevel, args...)
|
||||
}
|
||||
func (this *Logger) Errorln(args ...interface{}) {
|
||||
this.Logln(ErrorLevel, args...)
|
||||
}
|
||||
func (this *Logger) Fatalln(args ...interface{}) {
|
||||
this.Logln(FatalLevel, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
func (this *Logger) Panicln(args ...interface{}) {
|
||||
this.Logln(PanicLevel, args...)
|
||||
}
|
||||
func (this *Logger) Logln(level Loglevel, args ...interface{}) {
|
||||
if this.level.Enabled(level) {
|
||||
this.log(level, this.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Logger) log(level Loglevel, msg string, args ...Field) {
|
||||
entry := this.check(level, msg, args...)
|
||||
this.write(entry)
|
||||
if level <= PanicLevel {
|
||||
panic(entry)
|
||||
}
|
||||
putEntry(entry)
|
||||
}
|
||||
|
||||
func (this *Logger) check(level Loglevel, msg string, args ...Field) (entry *Entry) {
|
||||
entry = getEntry()
|
||||
entry.Name = this.name
|
||||
entry.Time = time.Now()
|
||||
entry.Level = level
|
||||
entry.Message = msg
|
||||
entry.WithFields(args...)
|
||||
addStack := this.addStack.Enabled(level)
|
||||
if !this.addCaller && !addStack {
|
||||
return
|
||||
}
|
||||
stackDepth := stacktraceFirst
|
||||
if addStack {
|
||||
stackDepth = stacktraceFull
|
||||
}
|
||||
stack := captureStacktrace(this.callerSkip+callerSkipOffset, stackDepth)
|
||||
defer stack.Free()
|
||||
if stack.Count() == 0 {
|
||||
if this.addCaller {
|
||||
if entry.Err != "" {
|
||||
entry.Err = entry.Err + ",error: failed to get caller"
|
||||
} else {
|
||||
entry.Err = "error:failed to get caller"
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
frame, more := stack.Next()
|
||||
if this.addCaller {
|
||||
entry.Caller.Defined = frame.PC != 0
|
||||
entry.Caller.PC = frame.PC
|
||||
entry.Caller.File = frame.File
|
||||
entry.Caller.Line = frame.Line
|
||||
entry.Caller.Function = frame.Function
|
||||
}
|
||||
if addStack {
|
||||
buffer := pools.BufferPoolGet()
|
||||
defer buffer.Free()
|
||||
|
||||
stackfmt := newStackFormatter(buffer)
|
||||
|
||||
stackfmt.FormatFrame(frame)
|
||||
if more {
|
||||
stackfmt.FormatStack(stack)
|
||||
}
|
||||
entry.Caller.Stack = buffer.String()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Logger) write(entry *Entry) {
|
||||
buf, err := this.formatter.Format(this.config, entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
||||
return
|
||||
}
|
||||
err = this.out.WriteTo(buf.Bytes())
|
||||
buf.Free()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain write, %v\n", err)
|
||||
return
|
||||
}
|
||||
if entry.Level < ErrorLevel {
|
||||
this.out.Sync()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Logger) sprintlnn(args ...interface{}) string {
|
||||
msg := fmt.Sprintln(args...)
|
||||
return msg[:len(msg)-1]
|
||||
}
|
@ -1,114 +1,139 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"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
|
||||
TextEncoder LogEncoder = iota
|
||||
JSONEncoder
|
||||
)
|
||||
|
||||
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天
|
||||
FileName string //日志文件名包含
|
||||
Loglevel Loglevel //日志输出级别
|
||||
IsDebug bool //是否是开发模式
|
||||
ReportCaller bool //是否输出堆栈信息
|
||||
CallerSkip int //堆栈深度
|
||||
Encoder LogEncoder //日志输出样式
|
||||
CupTimeTime int //日志分割时间 单位 小时
|
||||
MaxAgeTime int //日志最大保存时间 单位天
|
||||
MaxBackups int //最大备份日志个数
|
||||
Compress bool //是否压缩备份日志
|
||||
}
|
||||
|
||||
///日志文件名包含
|
||||
func SetFileName(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.FileName = v
|
||||
}
|
||||
}
|
||||
|
||||
//是否是开发模式
|
||||
func SetIsDebug(v bool) Option {
|
||||
return func(o *Options) {
|
||||
o.IsDebug = v
|
||||
}
|
||||
}
|
||||
|
||||
///日志输出级别 debug info warning error fatal panic
|
||||
func SetLoglevel(v Loglevel) Option {
|
||||
return func(o *Options) {
|
||||
o.Loglevel = v
|
||||
}
|
||||
}
|
||||
|
||||
func SetDebugMode(v bool) Option {
|
||||
func SetReportCaller(v bool) Option {
|
||||
return func(o *Options) {
|
||||
o.Debugmode = v
|
||||
o.ReportCaller = v
|
||||
}
|
||||
}
|
||||
func SetCallerSkip(v int) Option {
|
||||
return func(o *Options) {
|
||||
o.CallerSkip = v
|
||||
}
|
||||
}
|
||||
|
||||
///日志输出样式
|
||||
func SetEncoder(v LogEncoder) Option {
|
||||
return func(o *Options) {
|
||||
o.Encoder = v
|
||||
}
|
||||
}
|
||||
func SetLoglayer(v int) Option {
|
||||
|
||||
///日志分割时间 单位 小时
|
||||
func SetRotationTime(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
|
||||
o.CupTimeTime = 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,
|
||||
///日志最大保存时间 单位天
|
||||
func SetMaxAgeTime(v int) Option {
|
||||
return func(o *Options) {
|
||||
o.MaxAgeTime = v
|
||||
}
|
||||
}
|
||||
|
||||
///日志备份最大文件数
|
||||
func SetMaxBackups(v int) Option {
|
||||
return func(o *Options) {
|
||||
o.MaxBackups = v
|
||||
}
|
||||
}
|
||||
|
||||
///是否压缩备份日志
|
||||
func SetCompress(v bool) Option {
|
||||
return func(o *Options) {
|
||||
o.Compress = v
|
||||
}
|
||||
}
|
||||
func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) {
|
||||
options = &Options{
|
||||
FileName: "log",
|
||||
Loglevel: DebugLevel,
|
||||
CupTimeTime: 24,
|
||||
MaxAgeTime: 7,
|
||||
MaxBackups: 250,
|
||||
Compress: false,
|
||||
Encoder: TextEncoder,
|
||||
CallerSkip: 0,
|
||||
ReportCaller: false,
|
||||
IsDebug: true,
|
||||
}
|
||||
if config != nil {
|
||||
mapstructure.Decode(config, &options)
|
||||
mapstructure.Decode(config, options)
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
o(options)
|
||||
}
|
||||
return options
|
||||
if options.CupTimeTime <= 0 || options.MaxAgeTime <= 0 {
|
||||
err = errors.New("log options RotationTime or MaxAgeTime is zero!")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func newOptionsByOption(opts ...Option) Options {
|
||||
options := Options{
|
||||
FileName: "./lego.log",
|
||||
Loglevel: WarnLevel,
|
||||
Debugmode: false,
|
||||
Loglayer: 2,
|
||||
LogMaxSize: 1024,
|
||||
LogMaxBackups: 10,
|
||||
LogMaxAge: 7,
|
||||
func newOptionsByOption(opts ...Option) (options *Options, err error) {
|
||||
options = &Options{
|
||||
FileName: "log.log",
|
||||
Loglevel: DebugLevel,
|
||||
CupTimeTime: 24,
|
||||
MaxAgeTime: 7,
|
||||
MaxBackups: 250,
|
||||
Compress: false,
|
||||
Encoder: TextEncoder,
|
||||
CallerSkip: 0,
|
||||
ReportCaller: false,
|
||||
IsDebug: true,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
o(options)
|
||||
}
|
||||
return options
|
||||
return
|
||||
}
|
||||
|
156
lego/sys/log/stacktrace.go
Normal file
156
lego/sys/log/stacktrace.go
Normal file
@ -0,0 +1,156 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"go_dreamfactory/lego/utils/pools"
|
||||
)
|
||||
|
||||
var _stacktracePool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &stacktrace{
|
||||
storage: make([]uintptr, 64),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
type stacktrace struct {
|
||||
pcs []uintptr // program counters; always a subslice of storage
|
||||
frames *runtime.Frames
|
||||
|
||||
// The size of pcs varies depending on requirements:
|
||||
// it will be one if the only the first frame was requested,
|
||||
// and otherwise it will reflect the depth of the call stack.
|
||||
//
|
||||
// storage decouples the slice we need (pcs) from the slice we pool.
|
||||
// We will always allocate a reasonably large storage, but we'll use
|
||||
// only as much of it as we need.
|
||||
storage []uintptr
|
||||
}
|
||||
|
||||
// stacktraceDepth specifies how deep of a stack trace should be captured.
|
||||
type stacktraceDepth int
|
||||
|
||||
const callerSkipOffset = 2
|
||||
const (
|
||||
// stacktraceFirst captures only the first frame.
|
||||
stacktraceFirst stacktraceDepth = iota
|
||||
|
||||
// stacktraceFull captures the entire call stack, allocating more
|
||||
// storage for it if needed.
|
||||
stacktraceFull
|
||||
)
|
||||
|
||||
// captureStacktrace captures a stack trace of the specified depth, skipping
|
||||
// the provided number of frames. skip=0 identifies the caller of
|
||||
// captureStacktrace.
|
||||
//
|
||||
// The caller must call Free on the returned stacktrace after using it.
|
||||
func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
|
||||
stack := _stacktracePool.Get().(*stacktrace)
|
||||
|
||||
switch depth {
|
||||
case stacktraceFirst:
|
||||
stack.pcs = stack.storage[:1]
|
||||
case stacktraceFull:
|
||||
stack.pcs = stack.storage
|
||||
}
|
||||
|
||||
// Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers
|
||||
// itself. +2 to skip captureStacktrace and runtime.Callers.
|
||||
numFrames := runtime.Callers(
|
||||
skip+2,
|
||||
stack.pcs,
|
||||
)
|
||||
|
||||
// runtime.Callers truncates the recorded stacktrace if there is no
|
||||
// room in the provided slice. For the full stack trace, keep expanding
|
||||
// storage until there are fewer frames than there is room.
|
||||
if depth == stacktraceFull {
|
||||
pcs := stack.pcs
|
||||
for numFrames == len(pcs) {
|
||||
pcs = make([]uintptr, len(pcs)*2)
|
||||
numFrames = runtime.Callers(skip+2, pcs)
|
||||
}
|
||||
|
||||
// Discard old storage instead of returning it to the pool.
|
||||
// This will adjust the pool size over time if stack traces are
|
||||
// consistently very deep.
|
||||
stack.storage = pcs
|
||||
stack.pcs = pcs[:numFrames]
|
||||
} else {
|
||||
stack.pcs = stack.pcs[:numFrames]
|
||||
}
|
||||
|
||||
stack.frames = runtime.CallersFrames(stack.pcs)
|
||||
return stack
|
||||
}
|
||||
|
||||
// Free releases resources associated with this stacktrace
|
||||
// and returns it back to the pool.
|
||||
func (st *stacktrace) Free() {
|
||||
st.frames = nil
|
||||
st.pcs = nil
|
||||
_stacktracePool.Put(st)
|
||||
}
|
||||
|
||||
// Count reports the total number of frames in this stacktrace.
|
||||
// Count DOES NOT change as Next is called.
|
||||
func (st *stacktrace) Count() int {
|
||||
return len(st.pcs)
|
||||
}
|
||||
|
||||
// Next returns the next frame in the stack trace,
|
||||
// and a boolean indicating whether there are more after it.
|
||||
func (st *stacktrace) Next() (_ runtime.Frame, more bool) {
|
||||
return st.frames.Next()
|
||||
}
|
||||
|
||||
func takeStacktrace(skip int) string {
|
||||
stack := captureStacktrace(skip+1, stacktraceFull)
|
||||
defer stack.Free()
|
||||
|
||||
buffer := pools.BufferPoolGet()
|
||||
defer buffer.Free()
|
||||
|
||||
stackfmt := newStackFormatter(buffer)
|
||||
stackfmt.FormatStack(stack)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// stackFormatter formats a stack trace into a readable string representation.
|
||||
type stackFormatter struct {
|
||||
b *pools.Buffer
|
||||
nonEmpty bool // whehther we've written at least one frame already
|
||||
}
|
||||
|
||||
// newStackFormatter builds a new stackFormatter.
|
||||
func newStackFormatter(b *pools.Buffer) stackFormatter {
|
||||
return stackFormatter{b: b}
|
||||
}
|
||||
|
||||
// FormatStack formats all remaining frames in the provided stacktrace -- minus
|
||||
// the final runtime.main/runtime.goexit frame.
|
||||
func (sf *stackFormatter) FormatStack(stack *stacktrace) {
|
||||
// Note: On the last iteration, frames.Next() returns false, with a valid
|
||||
// frame, but we ignore this frame. The last frame is a a runtime frame which
|
||||
// adds noise, since it's only either runtime.main or runtime.goexit.
|
||||
for frame, more := stack.Next(); more; frame, more = stack.Next() {
|
||||
sf.FormatFrame(frame)
|
||||
}
|
||||
}
|
||||
|
||||
// FormatFrame formats the given frame.
|
||||
func (sf *stackFormatter) FormatFrame(frame runtime.Frame) {
|
||||
if sf.nonEmpty {
|
||||
sf.b.AppendByte('\n')
|
||||
}
|
||||
sf.nonEmpty = true
|
||||
sf.b.AppendString(frame.Function)
|
||||
sf.b.AppendByte('\n')
|
||||
sf.b.AppendByte('\t')
|
||||
sf.b.AppendString(frame.File)
|
||||
sf.b.AppendByte(':')
|
||||
sf.b.AppendInt(int64(frame.Line))
|
||||
}
|
@ -13,14 +13,18 @@ type TestData struct {
|
||||
Age int32
|
||||
}
|
||||
|
||||
var sys log.ILog
|
||||
func (this *TestData) Log() {
|
||||
sys.Error("妈妈咪呀!")
|
||||
}
|
||||
|
||||
var sys log.ISys
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if sys, err = log.NewSys(
|
||||
log.SetFileName("./log.log"),
|
||||
log.SetDebugMode(false),
|
||||
log.SetLoglayer(2),
|
||||
log.SetFileName("log.log"),
|
||||
log.SetIsDebug(false),
|
||||
log.SetEncoder(log.TextEncoder),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
@ -28,10 +32,12 @@ func TestMain(m *testing.M) {
|
||||
defer os.Exit(m.Run())
|
||||
}
|
||||
func Test_sys(t *testing.T) {
|
||||
sys.Error("测试日志接口代码!")
|
||||
data := &TestData{}
|
||||
data.Log()
|
||||
}
|
||||
|
||||
func Benchmark_Ability_Zap(b *testing.B) {
|
||||
//性能测试
|
||||
func Benchmark_Ability(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ { //use b.N for looping
|
||||
sys.Error("妈妈咪呀!")
|
||||
}
|
||||
|
132
lego/sys/log/turnlog.go
Normal file
132
lego/sys/log/turnlog.go
Normal file
@ -0,0 +1,132 @@
|
||||
package log
|
||||
|
||||
func NewTurnlog(isturnon bool, log ILogger) ILogger {
|
||||
return &Turnlog{
|
||||
isturnon: isturnon,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
type Turnlog struct {
|
||||
isturnon bool
|
||||
log ILogger
|
||||
}
|
||||
|
||||
func (this *Turnlog) SetName(name string) {
|
||||
if this.log != nil {
|
||||
this.log.SetName(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Turnlog) Enabled(lvl Loglevel) bool {
|
||||
if this.isturnon && this.log != nil {
|
||||
return this.log.Enabled(lvl)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Debug(msg string, args ...Field) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Debug(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Info(msg string, args ...Field) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Info(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Print(msg string, args ...Field) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Print(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Warn(msg string, args ...Field) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Warn(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Error(msg string, args ...Field) {
|
||||
if this.log != nil {
|
||||
this.log.Error(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Panic(msg string, args ...Field) {
|
||||
if this.log != nil {
|
||||
this.log.Panic(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Fatal(msg string, args ...Field) {
|
||||
if this.log != nil {
|
||||
this.log.Fatal(msg, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Debugf(format string, args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Debugf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Infof(format string, args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Infof(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Printf(format string, args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Warnf(format string, args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Warnf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Errorf(format string, args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Errorf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Fatalf(format string, args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Fatalf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Panicf(format string, args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Panicf(format, args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Debugln(args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Debugln(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Infoln(args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Infoln(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Println(args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Println(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Warnln(args ...interface{}) {
|
||||
if this.isturnon && this.log != nil {
|
||||
this.log.Warnln(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Errorln(args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Errorln(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Fatalln(args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Fatalln(args...)
|
||||
}
|
||||
}
|
||||
func (this *Turnlog) Panicln(args ...interface{}) {
|
||||
if this.log != nil {
|
||||
this.log.Panicln(args...)
|
||||
}
|
||||
}
|
87
lego/sys/log/write_syncer.go
Normal file
87
lego/sys/log/write_syncer.go
Normal file
@ -0,0 +1,87 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/multierr"
|
||||
)
|
||||
|
||||
func AddWrites(w ...IWrite) IWrite {
|
||||
ws := make(writeTree, 0, len(w))
|
||||
for _, v := range w {
|
||||
ws = append(ws, v)
|
||||
}
|
||||
return ws
|
||||
}
|
||||
|
||||
type writeTree []IWrite
|
||||
|
||||
func (mc writeTree) WriteTo(bs []byte) error {
|
||||
var err error
|
||||
for i := range mc {
|
||||
err = multierr.Append(err, mc[i].WriteTo(bs))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (mc writeTree) Sync() error {
|
||||
var err error
|
||||
for i := range mc {
|
||||
err = multierr.Append(err, mc[i].Sync())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type IWriteSyncer interface {
|
||||
io.Writer
|
||||
Sync() error
|
||||
}
|
||||
type IWrite interface {
|
||||
WriteTo(bs []byte) error
|
||||
Sync() error
|
||||
}
|
||||
|
||||
func AddSync(w io.Writer) IWrite {
|
||||
switch w := w.(type) {
|
||||
case IWrite:
|
||||
return w
|
||||
default:
|
||||
return writerWrapper{w}
|
||||
}
|
||||
}
|
||||
|
||||
type writerWrapper struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (w writerWrapper) WriteTo(bs []byte) error {
|
||||
_, err := w.Write(bs)
|
||||
return err
|
||||
}
|
||||
func (w writerWrapper) Sync() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func Lock(w IWriteSyncer) IWrite {
|
||||
return &lockedWriteSyncer{w: w}
|
||||
}
|
||||
|
||||
type lockedWriteSyncer struct {
|
||||
sync.Mutex
|
||||
w IWriteSyncer
|
||||
}
|
||||
|
||||
func (s *lockedWriteSyncer) WriteTo(bs []byte) error {
|
||||
s.Lock()
|
||||
_, err := s.w.Write(bs)
|
||||
s.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *lockedWriteSyncer) Sync() error {
|
||||
s.Lock()
|
||||
err := s.w.Sync()
|
||||
s.Unlock()
|
||||
return err
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
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...)
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
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)
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
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)
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
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)
|
||||
}
|
@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec"
|
||||
"go_dreamfactory/lego/sys/redis/cluster"
|
||||
"go_dreamfactory/lego/sys/redis/single"
|
||||
"go_dreamfactory/lego/utils/codec/json"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
@ -378,41 +378,41 @@ func (this *Redis) Marshal(v interface{}) ([]byte, error) {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.Marshal(v)
|
||||
} else {
|
||||
return codec.MarshalJson(v)
|
||||
return json.Marshal(v)
|
||||
}
|
||||
}
|
||||
func (this *Redis) Unmarshal(data []byte, v interface{}) error {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.Unmarshal(data, v)
|
||||
} else {
|
||||
return codec.UnmarshalJson(data, v)
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
||||
}
|
||||
func (this *Redis) MarshalMap(val interface{}) (ret map[string]string, err error) {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.MarshalMap(val)
|
||||
} else {
|
||||
return codec.MarshalMapJson(val)
|
||||
return json.MarshalMap(val)
|
||||
}
|
||||
}
|
||||
func (this *Redis) UnmarshalMap(data map[string]string, val interface{}) (err error) {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.UnmarshalMap(data, val)
|
||||
} else {
|
||||
return codec.UnmarshalMapJson(data, val)
|
||||
return json.UnmarshalMap(data, val)
|
||||
}
|
||||
}
|
||||
func (this *Redis) MarshalSlice(val interface{}) (ret []string, err error) {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.MarshalSlice(val)
|
||||
} else {
|
||||
return codec.MarshalSliceJson(val)
|
||||
return json.MarshalSlice(val)
|
||||
}
|
||||
}
|
||||
func (this *Redis) UnmarshalSlice(data []string, val interface{}) (err error) {
|
||||
if this.options.Codec != nil {
|
||||
return this.options.Codec.UnmarshalSlice(data, val)
|
||||
} else {
|
||||
return codec.UnmarshalSliceJson(data, val)
|
||||
return json.UnmarshalSlice(data, val)
|
||||
}
|
||||
}
|
||||
|
@ -1,391 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
hash "github.com/mitchellh/hashstructure"
|
||||
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/api/watch"
|
||||
)
|
||||
|
||||
func newConsul(options Options) (sys *Consul_Registry, err error) {
|
||||
sys = &Consul_Registry{
|
||||
options: options,
|
||||
}
|
||||
config := api.DefaultConfig()
|
||||
if len(options.Consul_Addr) > 0 {
|
||||
config.Address = options.Consul_Addr
|
||||
}
|
||||
if sys.client, err = api.NewClient(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sys.snodeWP, err = watch.Parse(map[string]interface{}{"type": "services"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sys.snodeWP.Handler = sys.shandler
|
||||
sys.options.Consul_Addr = config.Address
|
||||
sys.shash = make(map[string]uint64)
|
||||
sys.services = make(map[string]*ServiceNode)
|
||||
sys.rpcsubs = make(map[core.Rpc_Key][]*ServiceNode)
|
||||
sys.watchers = make(map[string]*watch.Plan)
|
||||
sys.closeSig = make(chan bool)
|
||||
sys.isstart = false
|
||||
return
|
||||
}
|
||||
|
||||
type Consul_Registry struct {
|
||||
options Options
|
||||
client *api.Client
|
||||
snodeWP *watch.Plan
|
||||
isstart bool
|
||||
closeSig chan bool
|
||||
shash map[string]uint64
|
||||
slock sync.RWMutex
|
||||
services map[string]*ServiceNode
|
||||
rlock sync.RWMutex
|
||||
rpcsubs map[core.Rpc_Key][]*ServiceNode
|
||||
watchers map[string]*watch.Plan
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) Start() (err error) {
|
||||
if err = this.getServices(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = this.registerSNode(&ServiceNode{
|
||||
Tag: this.options.Service.GetTag(),
|
||||
Id: this.options.Service.GetId(),
|
||||
IP: this.options.Service.GetIp(),
|
||||
Port: this.options.Service.GetPort(),
|
||||
Type: this.options.Service.GetType(),
|
||||
Category: this.options.Service.GetCategory(),
|
||||
Version: this.options.Service.GetVersion(),
|
||||
RpcId: this.options.Service.GetRpcId(),
|
||||
PreWeight: this.options.Service.GetPreWeight(),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
go this.snodeWP.Run(this.options.Consul_Addr)
|
||||
go this.run()
|
||||
this.isstart = true
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) Stop() (err error) {
|
||||
this.closeSig <- true
|
||||
this.isstart = false
|
||||
this.snodeWP.Stop()
|
||||
this.deregisterSNode()
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) PushServiceInfo() (err error) {
|
||||
if this.isstart {
|
||||
err = this.registerSNode(&ServiceNode{
|
||||
Tag: this.options.Service.GetTag(),
|
||||
Id: this.options.Service.GetId(),
|
||||
IP: this.options.Service.GetIp(),
|
||||
Port: this.options.Service.GetPort(),
|
||||
Type: this.options.Service.GetType(),
|
||||
Category: this.options.Service.GetCategory(),
|
||||
Version: this.options.Service.GetVersion(),
|
||||
RpcId: this.options.Service.GetRpcId(),
|
||||
PreWeight: this.options.Service.GetPreWeight(),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) GetServiceById(sId string) (n *ServiceNode, err error) {
|
||||
this.slock.RLock()
|
||||
n, ok := this.services[sId]
|
||||
this.slock.RUnlock()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("No Found %s", sId)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) GetServiceByType(sType string) (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
if v.Type == sType {
|
||||
n = append(n, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) GetAllServices() (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
n = append(n, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) GetServiceByCategory(category core.S_Category) (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
if v.Category == category {
|
||||
n = append(n, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Consul_Registry) GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) {
|
||||
n = make([]*ServiceNode, 0)
|
||||
this.rlock.RLock()
|
||||
d, ok := this.rpcsubs[rId]
|
||||
this.rlock.RUnlock()
|
||||
if ok {
|
||||
n = d
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//内部函数-------------------------------------------------------------------------------------------------------------------------
|
||||
func (this *Consul_Registry) run() {
|
||||
t := time.NewTicker(time.Duration(this.options.Consul_RegisterInterval) * time.Second)
|
||||
locp:
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
err := this.PushServiceInfo()
|
||||
if err != nil {
|
||||
log.Warnf("service run Server.Register error: ", err)
|
||||
}
|
||||
case <-this.closeSig:
|
||||
break locp
|
||||
}
|
||||
}
|
||||
log.Infof("Sys Registry is succ exit")
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) getServices() (err error) {
|
||||
services, err := this.client.Agent().Services()
|
||||
if err == nil {
|
||||
for _, v := range services {
|
||||
if v.Tags[0] == this.options.Service.GetTag() { //自能读取相同标签的服务
|
||||
this.addandupdataServiceNode(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (this *Consul_Registry) registerSNode(snode *ServiceNode) (err error) {
|
||||
h, err := hash.Hash(snode, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if v, ok := this.shash[snode.Id]; ok && v != 0 && v == h {
|
||||
if err := this.client.Agent().PassTTL("service:"+snode.Id, ""); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
deregTTL := this.getDeregisterTTL(time.Second * time.Duration(this.options.Consul_RegisterTTL))
|
||||
check := &api.AgentServiceCheck{
|
||||
TTL: fmt.Sprintf("%v", time.Second*time.Duration(this.options.Consul_RegisterTTL)),
|
||||
DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL),
|
||||
}
|
||||
asr := &api.AgentServiceRegistration{
|
||||
ID: snode.Id,
|
||||
Name: snode.Type,
|
||||
Tags: []string{this.options.Service.GetTag()},
|
||||
Check: check,
|
||||
Meta: map[string]string{
|
||||
"tag": snode.Tag,
|
||||
"ip": snode.IP,
|
||||
"port": fmt.Sprintf("%d", snode.Port),
|
||||
"category": string(snode.Category),
|
||||
"version": snode.Version,
|
||||
"rpcid": snode.RpcId,
|
||||
"preweight": fmt.Sprintf("%f", snode.PreWeight),
|
||||
},
|
||||
}
|
||||
if err := this.client.Agent().ServiceRegister(asr); err != nil {
|
||||
return err
|
||||
}
|
||||
return this.client.Agent().PassTTL("service:"+snode.Id, "")
|
||||
}
|
||||
func (this *Consul_Registry) deregisterSNode() (err error) {
|
||||
return this.client.Agent().ServiceDeregister(this.options.Service.GetId())
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) addandupdataServiceNode(as *api.AgentService) (sn *ServiceNode, err error) {
|
||||
|
||||
tag := as.Meta["tag"]
|
||||
ip := as.Meta["ip"]
|
||||
port, err := strconv.ParseInt(as.Meta["port"], 10, 64)
|
||||
if err != nil {
|
||||
log.Errorf("port 读取服务节点异常:%s err:%v", as.Meta["port"], err)
|
||||
return
|
||||
}
|
||||
category := as.Meta["category"]
|
||||
version := as.Meta["version"]
|
||||
rpcid := as.Meta["rpcid"]
|
||||
preweight, err := strconv.ParseFloat(as.Meta["preweight"], 64)
|
||||
if err != nil {
|
||||
log.Errorf("registry 读取服务节点异常:%s err:%v", as.Meta["preweight"], err)
|
||||
return
|
||||
}
|
||||
|
||||
snode := &ServiceNode{
|
||||
Tag: tag,
|
||||
Type: as.Service,
|
||||
Category: core.S_Category(category),
|
||||
Id: as.ID,
|
||||
IP: ip,
|
||||
Port: int(port),
|
||||
Version: version,
|
||||
RpcId: rpcid,
|
||||
PreWeight: preweight,
|
||||
}
|
||||
if h, err := hash.Hash(snode, nil); err == nil {
|
||||
_, ok := this.services[snode.Id]
|
||||
if !ok {
|
||||
log.Infof("发现新的服务【%s:%s】", snode.Id, snode.Version)
|
||||
this.rlock.Lock()
|
||||
this.services[snode.Id] = snode
|
||||
this.shash[snode.Id] = h
|
||||
this.rlock.Unlock()
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.FindServiceHandlefunc(*snode)
|
||||
}
|
||||
} else {
|
||||
this.rlock.RLock()
|
||||
v, ok := this.shash[snode.Id]
|
||||
this.rlock.RUnlock()
|
||||
if !ok || v != h { //校验不一致
|
||||
// log.Debugf("更新服务【%s】", snode.Id)
|
||||
this.rlock.Lock()
|
||||
this.services[snode.Id] = snode
|
||||
this.shash[snode.Id] = h
|
||||
this.rlock.Unlock()
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.UpDataServiceHandlefunc(*snode)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Errorf("registry 校验服务 hash 值异常:%s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) removeServiceNode(sId string) {
|
||||
this.rlock.RLock()
|
||||
_, ok := this.services[sId]
|
||||
this.rlock.RUnlock()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Infof("丢失服务【%s】", sId)
|
||||
this.rlock.Lock()
|
||||
delete(this.shash, sId)
|
||||
delete(this.services, sId)
|
||||
this.rlock.Unlock()
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.LoseServiceHandlefunc(sId)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) shandler(idx uint64, data interface{}) {
|
||||
services, ok := data.(map[string][]string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for k, v := range services {
|
||||
if len(v) > 0 {
|
||||
if v[0] == this.options.Service.GetTag() {
|
||||
_, ok := this.watchers[k]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
wp, err := watch.Parse(map[string]interface{}{
|
||||
"type": "service",
|
||||
"service": k,
|
||||
})
|
||||
if err == nil {
|
||||
wp.Handler = this.snodehandler
|
||||
go wp.Run(this.options.Consul_Addr)
|
||||
this.watchers[k] = wp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
temp := make(map[string]*ServiceNode)
|
||||
this.rlock.RLock()
|
||||
for k, v := range this.services {
|
||||
temp[k] = v
|
||||
}
|
||||
this.rlock.RUnlock()
|
||||
for k, v := range this.watchers {
|
||||
if _, ok := services[k]; !ok { //不存在了
|
||||
v.Stop()
|
||||
delete(this.watchers, k)
|
||||
for k1, v1 := range temp {
|
||||
if v1.Type == k {
|
||||
this.removeServiceNode(k1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) snodehandler(idx uint64, data interface{}) {
|
||||
entries, ok := data.([]*api.ServiceEntry)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
stype := ""
|
||||
serviceMap := map[string]struct{}{}
|
||||
for _, v := range entries {
|
||||
isdele := false
|
||||
for _, check := range v.Checks {
|
||||
if check.Status == "critical" {
|
||||
this.removeServiceNode(v.Service.ID)
|
||||
isdele = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isdele {
|
||||
this.addandupdataServiceNode(v.Service)
|
||||
stype = v.Service.Service
|
||||
serviceMap[v.Service.ID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
temp := make(map[string]*ServiceNode)
|
||||
this.rlock.RLock()
|
||||
for k, v := range this.services {
|
||||
temp[k] = v
|
||||
}
|
||||
this.rlock.RUnlock()
|
||||
for _, v := range temp {
|
||||
if v.Type == stype {
|
||||
if _, ok := serviceMap[v.Id]; !ok {
|
||||
this.removeServiceNode(v.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Consul_Registry) getDeregisterTTL(t time.Duration) time.Duration {
|
||||
// splay slightly for the watcher?
|
||||
splay := time.Second * 5
|
||||
deregTTL := t + splay
|
||||
// consul has a minimum timeout on deregistration of 1 minute.
|
||||
if t < time.Minute {
|
||||
deregTTL = time.Minute + splay
|
||||
}
|
||||
return deregTTL
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package registry
|
||||
|
||||
import "go_dreamfactory/lego/core"
|
||||
|
||||
type (
|
||||
IListener interface {
|
||||
FindServiceHandlefunc(snode ServiceNode)
|
||||
UpDataServiceHandlefunc(snode ServiceNode)
|
||||
LoseServiceHandlefunc(sId string)
|
||||
}
|
||||
ServiceNode struct {
|
||||
Tag string `json:"Tag"` //服务集群标签
|
||||
Type string `json:"Type"` //服务类型
|
||||
Category core.S_Category `json:"Category"` //服务列别
|
||||
Id string `json:"Id"` //服务Id
|
||||
Version string `json:"Version"` //服务版本
|
||||
IP string `json:"Ip"` //服务Ip
|
||||
Port int `json:"Port"` //端口
|
||||
RpcId string `json:"RpcId"` //服务通信Id
|
||||
PreWeight float64 `json:"PreWeight"` //服务负载权重
|
||||
}
|
||||
|
||||
ISys interface {
|
||||
Start() error
|
||||
Stop() error
|
||||
PushServiceInfo() (err error)
|
||||
GetServiceById(sId string) (n *ServiceNode, err error)
|
||||
GetServiceByType(sType string) (n []*ServiceNode)
|
||||
GetAllServices() (n []*ServiceNode)
|
||||
GetServiceByCategory(category core.S_Category) (n []*ServiceNode)
|
||||
GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode)
|
||||
}
|
||||
)
|
||||
|
||||
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 Start() error {
|
||||
return defsys.Start()
|
||||
}
|
||||
func Stop() error {
|
||||
return defsys.Stop()
|
||||
}
|
||||
|
||||
func PushServiceInfo() (err error) {
|
||||
return defsys.PushServiceInfo()
|
||||
}
|
||||
|
||||
func GetServiceById(sId string) (n *ServiceNode, err error) {
|
||||
return defsys.GetServiceById(sId)
|
||||
}
|
||||
func GetServiceByType(sType string) (n []*ServiceNode) {
|
||||
return defsys.GetServiceByType(sType)
|
||||
}
|
||||
|
||||
func GetAllServices() (n []*ServiceNode) {
|
||||
return defsys.GetAllServices()
|
||||
}
|
||||
|
||||
func GetServiceByCategory(category core.S_Category) (n []*ServiceNode) {
|
||||
return defsys.GetServiceByCategory(category)
|
||||
}
|
||||
|
||||
func GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) {
|
||||
return defsys.GetRpcSubById(rId)
|
||||
}
|
||||
|
||||
func SubscribeRpc(rpc core.Rpc_Key) {
|
||||
|
||||
}
|
@ -1,413 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
|
||||
hash "github.com/mitchellh/hashstructure"
|
||||
"github.com/nacos-group/nacos-sdk-go/clients"
|
||||
"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 newNacos(options Options) (sys *Nacos_Registry, err error) {
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
sys = &Nacos_Registry{
|
||||
options: options,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
shash: make(map[string]uint64),
|
||||
services: make(map[string]*ServiceNode),
|
||||
subscribe: make(map[string]*vo.SubscribeParam),
|
||||
rpcsubs: make(map[core.Rpc_Key][]*ServiceNode),
|
||||
}
|
||||
// 创建clientConfig
|
||||
clientConfig := constant.ClientConfig{
|
||||
NamespaceId: options.Nacos_NamespaceId,
|
||||
TimeoutMs: options.Nacos_TimeoutMs,
|
||||
BeatInterval: options.Nacos_BeatInterval,
|
||||
Username: options.Nacos_UserName,
|
||||
Password: options.Nacos_Password,
|
||||
NotLoadCacheAtStart: true,
|
||||
UpdateCacheWhenEmpty: true,
|
||||
LogDir: "nacos/log",
|
||||
CacheDir: "nacos/cache",
|
||||
RotateTime: "1h",
|
||||
MaxAge: 3,
|
||||
LogLevel: "error",
|
||||
}
|
||||
// 至少一个ServerConfig
|
||||
serverConfigs := []constant.ServerConfig{
|
||||
{
|
||||
IpAddr: options.Nacos_NacosAddr,
|
||||
ContextPath: "/nacos",
|
||||
Port: options.Nacos_Port,
|
||||
Scheme: "http",
|
||||
},
|
||||
}
|
||||
|
||||
// 创建服务发现客户端的另一种方式 (推荐)
|
||||
sys.client, err = clients.NewNamingClient(
|
||||
vo.NacosClientParam{
|
||||
ClientConfig: &clientConfig,
|
||||
ServerConfigs: serverConfigs,
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
type Nacos_Registry struct {
|
||||
options Options
|
||||
client naming_client.INamingClient
|
||||
isstart bool
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
slock sync.RWMutex
|
||||
shash map[string]uint64
|
||||
subscribe map[string]*vo.SubscribeParam
|
||||
services map[string]*ServiceNode
|
||||
rlock sync.RWMutex
|
||||
rpcsubs map[core.Rpc_Key][]*ServiceNode
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) Start() (err error) {
|
||||
if err = this.getServices(); err != nil && err.Error() != "instance list is empty!" {
|
||||
return
|
||||
}
|
||||
if err = this.registerSNode(&ServiceNode{
|
||||
Tag: this.options.Service.GetTag(),
|
||||
Id: this.options.Service.GetId(),
|
||||
IP: this.options.Service.GetIp(),
|
||||
Port: this.options.Service.GetPort(),
|
||||
Type: this.options.Service.GetType(),
|
||||
Category: this.options.Service.GetCategory(),
|
||||
Version: this.options.Service.GetVersion(),
|
||||
RpcId: this.options.Service.GetRpcId(),
|
||||
PreWeight: this.options.Service.GetPreWeight(),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
ctx1, _ := context.WithCancel(this.ctx)
|
||||
go this.run(ctx1)
|
||||
ctx2, _ := context.WithCancel(this.ctx)
|
||||
go this.listener(ctx2)
|
||||
this.isstart = true
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) Stop() (err error) {
|
||||
this.cancel()
|
||||
this.isstart = false
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) PushServiceInfo() (err error) {
|
||||
if this.isstart {
|
||||
err = this.registerSNode(&ServiceNode{
|
||||
Tag: this.options.Service.GetTag(),
|
||||
Id: this.options.Service.GetId(),
|
||||
IP: this.options.Service.GetIp(),
|
||||
Port: this.options.Service.GetPort(),
|
||||
Type: this.options.Service.GetType(),
|
||||
Category: this.options.Service.GetCategory(),
|
||||
Version: this.options.Service.GetVersion(),
|
||||
RpcId: this.options.Service.GetRpcId(),
|
||||
PreWeight: this.options.Service.GetPreWeight(),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) GetServiceById(sId string) (n *ServiceNode, err error) {
|
||||
this.slock.RLock()
|
||||
n, ok := this.services[sId]
|
||||
this.slock.RUnlock()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("No Found %s", sId)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) GetServiceByType(sType string) (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
if v.Type == sType {
|
||||
n = append(n, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) GetAllServices() (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
n = append(n, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) GetServiceByCategory(category core.S_Category) (n []*ServiceNode) {
|
||||
this.slock.RLock()
|
||||
defer this.slock.RUnlock()
|
||||
n = make([]*ServiceNode, 0)
|
||||
for _, v := range this.services {
|
||||
if v.Category == category {
|
||||
n = append(n, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode) {
|
||||
n = make([]*ServiceNode, 0)
|
||||
this.rlock.RLock()
|
||||
d, ok := this.rpcsubs[rId]
|
||||
this.rlock.RUnlock()
|
||||
if ok {
|
||||
n = d
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//内部函数-------------------------------------------------------------------------------------------------------------------------
|
||||
func (this *Nacos_Registry) run(ctx context.Context) {
|
||||
t := time.NewTicker(time.Duration(this.options.Consul_RegisterInterval) * time.Second)
|
||||
defer t.Stop()
|
||||
locp:
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
err := this.PushServiceInfo()
|
||||
if err != nil {
|
||||
log.Warnf("service run Server.Register error: %v", err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
break locp
|
||||
}
|
||||
}
|
||||
log.Infof("Sys Registry is succ exit run")
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) listener(ctx context.Context) {
|
||||
var (
|
||||
slist model.ServiceList
|
||||
instances []model.Instance
|
||||
err error
|
||||
)
|
||||
t := time.NewTicker(time.Duration(this.options.Nacos_RegisterTTL) * time.Second)
|
||||
defer t.Stop()
|
||||
locp:
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
if slist, err = this.client.GetAllServicesInfo(vo.GetAllServiceInfoParam{
|
||||
NameSpace: this.options.Nacos_NamespaceId,
|
||||
GroupName: this.options.Service.GetTag(),
|
||||
PageNo: 1,
|
||||
PageSize: 100,
|
||||
}); err == nil {
|
||||
var service = make(map[string]struct{})
|
||||
for _, v := range slist.Doms {
|
||||
if instances, err = this.client.SelectInstances(vo.SelectInstancesParam{
|
||||
ServiceName: v,
|
||||
GroupName: this.options.Service.GetTag(),
|
||||
HealthyOnly: true,
|
||||
}); err == nil {
|
||||
for _, v1 := range instances {
|
||||
if v1.Enable && v1.Healthy {
|
||||
service[v] = struct{}{}
|
||||
this.addandupdataServiceNode(v1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
temp := make(map[string]*ServiceNode)
|
||||
this.rlock.RLock()
|
||||
for k, v := range this.services {
|
||||
temp[k] = v
|
||||
}
|
||||
this.rlock.RUnlock()
|
||||
for k, v := range temp {
|
||||
if _, ok := service[k]; !ok { //不存在了 移除
|
||||
this.removeServiceNode(v.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
break locp
|
||||
}
|
||||
}
|
||||
log.Infof("Sys Registry is succ exit listener")
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) getServices() (err error) {
|
||||
var (
|
||||
slist model.ServiceList
|
||||
instances []model.Instance
|
||||
)
|
||||
if slist, err = this.client.GetAllServicesInfo(vo.GetAllServiceInfoParam{
|
||||
NameSpace: this.options.Nacos_NamespaceId,
|
||||
GroupName: this.options.Service.GetTag(),
|
||||
PageNo: 1,
|
||||
PageSize: 20,
|
||||
}); err == nil {
|
||||
for _, v := range slist.Doms {
|
||||
this.rlock.RLock()
|
||||
_, ok := this.services[v]
|
||||
this.rlock.RUnlock()
|
||||
if !ok {
|
||||
if instances, err = this.client.SelectInstances(vo.SelectInstancesParam{
|
||||
ServiceName: v,
|
||||
GroupName: this.options.Service.GetTag(),
|
||||
HealthyOnly: true,
|
||||
}); err == nil {
|
||||
for _, v1 := range instances {
|
||||
if v1.Enable && v1.Healthy {
|
||||
this.addandupdataServiceNode(v1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (this *Nacos_Registry) registerSNode(snode *ServiceNode) (err error) {
|
||||
h, err := hash.Hash(snode, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v, ok := this.shash[snode.Id]; ok && v != 0 && v == h { //没变化不用注册
|
||||
return
|
||||
}
|
||||
var (
|
||||
// success bool
|
||||
)
|
||||
this.deregisterSNode()
|
||||
_, err = this.client.RegisterInstance(vo.RegisterInstanceParam{
|
||||
Ip: snode.IP,
|
||||
Port: uint64(snode.Port),
|
||||
Weight: snode.PreWeight,
|
||||
GroupName: snode.Tag,
|
||||
ServiceName: snode.Id,
|
||||
Enable: true,
|
||||
Healthy: true,
|
||||
Ephemeral: true,
|
||||
Metadata: map[string]string{
|
||||
"id": snode.Id,
|
||||
"tag": snode.Tag,
|
||||
"type": string(snode.Type),
|
||||
"category": string(snode.Category),
|
||||
"version": fmt.Sprintf("%v", snode.Version),
|
||||
"rpcid": snode.RpcId,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) deregisterSNode() (err error) {
|
||||
_, err = this.client.DeregisterInstance(vo.DeregisterInstanceParam{
|
||||
Ip: this.options.Service.GetIp(),
|
||||
Port: 8848,
|
||||
ServiceName: this.options.Service.GetId(),
|
||||
GroupName: this.options.Service.GetTag(),
|
||||
})
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) addandupdataServiceNode(as model.Instance) (sn *ServiceNode, err error) {
|
||||
var (
|
||||
version string
|
||||
rpcid string
|
||||
snode *ServiceNode
|
||||
h uint64
|
||||
)
|
||||
version = as.Metadata["version"]
|
||||
rpcid = as.Metadata["rpcid"]
|
||||
snode = &ServiceNode{
|
||||
Tag: as.Metadata["tag"],
|
||||
Type: as.Metadata["type"],
|
||||
Category: core.S_Category(as.Metadata["category"]),
|
||||
Id: as.Metadata["id"],
|
||||
IP: as.Ip,
|
||||
Port: int(as.Port),
|
||||
Version: version,
|
||||
RpcId: rpcid,
|
||||
PreWeight: as.Weight,
|
||||
}
|
||||
if h, err = hash.Hash(snode, nil); err == nil {
|
||||
_, ok := this.services[snode.Id]
|
||||
if !ok {
|
||||
log.Infof("发现新的服务【%s:%s】", snode.Id, snode.Version)
|
||||
sub := &vo.SubscribeParam{
|
||||
ServiceName: snode.Id,
|
||||
GroupName: snode.Tag,
|
||||
SubscribeCallback: this.subscribecallback,
|
||||
}
|
||||
this.rlock.Lock()
|
||||
this.services[snode.Id] = snode
|
||||
this.shash[snode.Id] = h
|
||||
this.subscribe[snode.Id] = sub
|
||||
this.rlock.Unlock()
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.FindServiceHandlefunc(*snode)
|
||||
}
|
||||
err = this.client.Subscribe(sub)
|
||||
} else {
|
||||
this.rlock.RLock()
|
||||
v, ok := this.shash[snode.Id]
|
||||
this.rlock.RUnlock()
|
||||
if !ok || v != h { //校验不一致
|
||||
// log.Debugf("更新服务【%s】", snode.Id)
|
||||
this.rlock.Lock()
|
||||
this.services[snode.Id] = snode
|
||||
this.shash[snode.Id] = h
|
||||
this.rlock.Unlock()
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.UpDataServiceHandlefunc(*snode)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Errorf("registry 校验服务 hash 值异常:%s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *Nacos_Registry) removeServiceNode(sId string) {
|
||||
this.rlock.RLock()
|
||||
_, ok := this.services[sId]
|
||||
sub, _ := this.subscribe[sId]
|
||||
this.rlock.RUnlock()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Infof("丢失服务【%s】", sId)
|
||||
this.rlock.Lock()
|
||||
delete(this.services, sId)
|
||||
delete(this.subscribe, sId)
|
||||
delete(this.shash, sId)
|
||||
this.rlock.Unlock()
|
||||
this.client.Unsubscribe(sub)
|
||||
if this.options.Listener != nil { //异步通知
|
||||
go this.options.Listener.LoseServiceHandlefunc(sId)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Nacos_Registry) subscribecallback(services []model.SubscribeService, err error) {
|
||||
for _, v := range services {
|
||||
// log.Debugf("subscribecallback:%+v", v)
|
||||
this.addandupdataServiceNode(model.Instance{
|
||||
Valid: v.Valid,
|
||||
Enable: v.Enable,
|
||||
ServiceName: v.ServiceName,
|
||||
Ip: v.Ip,
|
||||
Port: v.Port,
|
||||
Metadata: v.Metadata,
|
||||
Weight: v.Weight,
|
||||
})
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/base"
|
||||
"go_dreamfactory/lego/utils/mapstructure"
|
||||
)
|
||||
|
||||
type RegistryType uint8
|
||||
|
||||
const (
|
||||
Registry_Consul RegistryType = iota
|
||||
Registry_Nacos
|
||||
Registry_Zookeeper
|
||||
)
|
||||
|
||||
type (
|
||||
Option func(*Options)
|
||||
Options struct {
|
||||
RegistryType RegistryType
|
||||
Service base.IClusterServiceBase
|
||||
Listener IListener
|
||||
Consul_Addr string
|
||||
Consul_RegisterInterval int //定期注册
|
||||
Consul_RegisterTTL int
|
||||
Nacos_NamespaceId string
|
||||
Nacos_NacosAddr string
|
||||
Nacos_Port uint64
|
||||
Nacos_UserName string
|
||||
Nacos_Password string
|
||||
Nacos_TimeoutMs uint64 //连接超时 ms
|
||||
Nacos_BeatInterval int64 //心跳间隔 ms
|
||||
Nacos_RegisterTTL int
|
||||
}
|
||||
)
|
||||
|
||||
func SetRegistryType(v RegistryType) Option {
|
||||
return func(o *Options) {
|
||||
o.RegistryType = v
|
||||
}
|
||||
}
|
||||
func SetService(v base.IClusterServiceBase) Option {
|
||||
return func(o *Options) {
|
||||
o.Service = v
|
||||
}
|
||||
}
|
||||
func SetListener(v IListener) Option {
|
||||
return func(o *Options) {
|
||||
o.Listener = v
|
||||
}
|
||||
}
|
||||
func SetConsul_Addr(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.Consul_Addr = v
|
||||
}
|
||||
}
|
||||
func SetConsul_RegisterInterval(v int) Option {
|
||||
return func(o *Options) {
|
||||
o.Consul_RegisterInterval = v
|
||||
}
|
||||
}
|
||||
func SetConsul_RegisterTTL(v int) Option {
|
||||
return func(o *Options) {
|
||||
o.Consul_RegisterTTL = v
|
||||
}
|
||||
}
|
||||
func SetNacos_NamespaceId(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_NamespaceId = v
|
||||
}
|
||||
}
|
||||
func SetNacos_NacosAddr(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_NacosAddr = v
|
||||
}
|
||||
}
|
||||
|
||||
func SetNacos_Port(v uint64) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_Port = v
|
||||
}
|
||||
}
|
||||
|
||||
func SetNacos_UserName(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_UserName = v
|
||||
}
|
||||
}
|
||||
|
||||
func SetNacos_Password(v string) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_Password = v
|
||||
}
|
||||
}
|
||||
|
||||
func SetNacos_TimeoutMs(v uint64) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_TimeoutMs = v
|
||||
}
|
||||
}
|
||||
func SetNacos_BeatInterval(v int64) Option {
|
||||
return func(o *Options) {
|
||||
o.Nacos_BeatInterval = v
|
||||
}
|
||||
}
|
||||
|
||||
func newOptions(config map[string]interface{}, opts ...Option) Options {
|
||||
options := Options{
|
||||
Consul_RegisterInterval: 10,
|
||||
Consul_RegisterTTL: 15,
|
||||
Nacos_TimeoutMs: 10000,
|
||||
Nacos_BeatInterval: 5000,
|
||||
Nacos_RegisterTTL: 8,
|
||||
}
|
||||
if config != nil {
|
||||
mapstructure.Decode(config, &options)
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func newOptionsByOption(opts ...Option) Options {
|
||||
options := Options{
|
||||
Consul_RegisterInterval: 10,
|
||||
Consul_RegisterTTL: 30,
|
||||
Nacos_TimeoutMs: 10000,
|
||||
Nacos_BeatInterval: 5000,
|
||||
Nacos_RegisterTTL: 8,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package registry
|
||||
|
||||
func newSys(options Options) (sys ISys, err error) {
|
||||
if options.RegistryType == Registry_Consul {
|
||||
sys, err = newConsul(options)
|
||||
} else if options.RegistryType == Registry_Nacos {
|
||||
sys, err = newNacos(options)
|
||||
}
|
||||
return
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package registry_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/nacos-group/nacos-sdk-go/clients"
|
||||
"github.com/nacos-group/nacos-sdk-go/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/vo"
|
||||
)
|
||||
|
||||
func Test_Sys_Nacose(t *testing.T) {
|
||||
// 创建clientConfig
|
||||
clientConfig := constant.ClientConfig{
|
||||
NamespaceId: "ac1b23d5-1c14-4485-9e08-f3cde8c83163",
|
||||
}
|
||||
// 至少一个ServerConfig
|
||||
serverConfigs := []constant.ServerConfig{
|
||||
{
|
||||
IpAddr: "172.20.27.126",
|
||||
ContextPath: "/nacos",
|
||||
Port: 8888,
|
||||
Scheme: "http",
|
||||
},
|
||||
}
|
||||
|
||||
// 创建服务发现客户端的另一种方式 (推荐)
|
||||
client, err := clients.NewNamingClient(
|
||||
vo.NacosClientParam{
|
||||
ClientConfig: &clientConfig,
|
||||
ServerConfigs: serverConfigs,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("初始化系统失败\n")
|
||||
}
|
||||
|
||||
// if succ, err := client.RegisterInstance(vo.RegisterInstanceParam{
|
||||
// Ip: "127.0.0.2",
|
||||
// Port: 8848,
|
||||
// Weight: 1,
|
||||
// ServiceName: "test_1",
|
||||
// Enable: true,
|
||||
// Healthy: true,
|
||||
// Ephemeral: true,
|
||||
// Metadata: map[string]string{
|
||||
// "type": "test",
|
||||
// "category": "test",
|
||||
// "version": fmt.Sprintf("%e", 1.0),
|
||||
// "rpcid": "rwercsfsdwer",
|
||||
// "rpcsubscribe": "{}",
|
||||
// },
|
||||
// }); err != nil {
|
||||
// fmt.Printf("RegisterInstance err:%v\n", err)
|
||||
// } else {
|
||||
// fmt.Printf("RegisterInstance succ:%v\n", succ)
|
||||
// }
|
||||
|
||||
if slist, err := client.GetAllServicesInfo(vo.GetAllServiceInfoParam{
|
||||
NameSpace: "ac1b23d5-1c14-4485-9e08-f3cde8c83163",
|
||||
GroupName: "datacollector",
|
||||
PageNo: 1,
|
||||
PageSize: 20,
|
||||
}); err != nil {
|
||||
fmt.Printf("GetAllServicesInfo err:%v\n", err)
|
||||
} else {
|
||||
fmt.Printf("GetAllServicesInfo :%+v\n", slist)
|
||||
for _, v := range slist.Doms {
|
||||
if instances, err := client.SelectInstances(vo.SelectInstancesParam{
|
||||
ServiceName: v,
|
||||
GroupName: "datacollector",
|
||||
HealthyOnly: true,
|
||||
}); err == nil {
|
||||
fmt.Printf("instances :%+v\n", instances)
|
||||
} else {
|
||||
fmt.Printf("instances err:%v\n", err)
|
||||
}
|
||||
// if services, err := client.SelectInstances(vo.SelectInstancesParam{
|
||||
// ServiceName: v,
|
||||
// HealthyOnly: true,
|
||||
// }); err != nil {
|
||||
// fmt.Printf("SelectInstances err:%v\n", err)
|
||||
// } else {
|
||||
// fmt.Printf("SelectInstances :%+v\n", services)
|
||||
// }
|
||||
// if services, err := client.SelectAllInstances(vo.SelectAllInstancesParam{
|
||||
// ServiceName: v,
|
||||
// }); err != nil {
|
||||
// fmt.Printf("SelectAllInstances err:%v\n", err)
|
||||
// } else {
|
||||
// fmt.Printf("SelectAllInstances :%+v\n", services)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Sys_Consul(t *testing.T) {
|
||||
config := api.DefaultConfig()
|
||||
config.Address = "172.20.27.145:10003"
|
||||
if client, err := api.NewClient(config); err != nil {
|
||||
fmt.Printf("NewClient Err:%v\n", err)
|
||||
return
|
||||
} else {
|
||||
if err := client.Agent().ServiceRegister(&api.AgentServiceRegistration{
|
||||
ID: "test",
|
||||
Name: "test",
|
||||
Tags: []string{"test"},
|
||||
Meta: map[string]string{},
|
||||
}); err != nil {
|
||||
fmt.Printf("ServiceRegister Err:%v\n", err)
|
||||
return
|
||||
} else {
|
||||
fmt.Printf("ServiceRegister Succ\n")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package registry
|
||||
|
||||
func newZookeeper(options Options) (sys *Zookeeper_Registry, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type Zookeeper_Registry struct {
|
||||
options Options
|
||||
}
|
@ -36,6 +36,7 @@ type Client struct {
|
||||
metadata string
|
||||
writeTimeout time.Duration
|
||||
AsyncWrite bool
|
||||
clusterMu sync.RWMutex
|
||||
clusterClients map[string]map[string]client.XClient //其他集群客户端
|
||||
connsMapMu sync.RWMutex
|
||||
conns map[string]net.Conn
|
||||
@ -51,15 +52,15 @@ func (this *Client) DoMessage() {
|
||||
for msg := range this.msgChan {
|
||||
go func(req *protocol.Message) {
|
||||
if req.ServicePath != "" && req.ServiceMethod != "" {
|
||||
this.Debugf("DoMessage :%v", req)
|
||||
this.options.Log.Debugf("DoMessage :%v", req)
|
||||
addr, ok := req.Metadata[ServiceAddrKey]
|
||||
if !ok {
|
||||
this.Errorf("Metadata no found ServiceAddrKey!")
|
||||
this.options.Log.Errorf("Metadata no found ServiceAddrKey!")
|
||||
return
|
||||
}
|
||||
conn, ok := this.conns[addr]
|
||||
if !ok {
|
||||
this.Errorf("no found conn addr:%s", addr)
|
||||
this.options.Log.Errorf("no found conn addr:%s", addr)
|
||||
return
|
||||
}
|
||||
res, _ := this.handleRequest(context.Background(), req)
|
||||
@ -86,6 +87,19 @@ func (this *Client) Stop() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//获取服务集群列表
|
||||
func (this *Client) GetServiceTags() []string {
|
||||
this.clusterMu.RLock()
|
||||
tags := make([]string, len(this.clusterClients))
|
||||
n := 0
|
||||
for k, _ := range this.clusterClients {
|
||||
tags[n] = k
|
||||
n++
|
||||
}
|
||||
this.clusterMu.RUnlock()
|
||||
return tags
|
||||
}
|
||||
|
||||
//注册Rpc 服务
|
||||
func (this *Client) RegisterFunction(fn interface{}) (err error) {
|
||||
_, err = this.registerFunction(this.options.ServiceType, fn, "", false)
|
||||
@ -247,12 +261,12 @@ func (this *Client) UpdateServer(servers map[string]*ServiceNode) {
|
||||
ServiceType: this.options.ServiceType,
|
||||
ServiceAddr: this.options.ServiceAddr},
|
||||
&ServiceNode{}); err != nil {
|
||||
this.Errorf("ShakeHands new node addr:%s err:%v", v.ServiceAddr, err)
|
||||
this.options.Log.Errorf("ShakeHands new node addr:%s err:%v", v.ServiceAddr, err)
|
||||
this.connectMapMu.Lock()
|
||||
delete(this.connecting, v.ServiceAddr)
|
||||
this.connectMapMu.Unlock()
|
||||
} else {
|
||||
this.Debugf("UpdateServer addr:%s ", v.ServiceAddr)
|
||||
this.options.Log.Debugf("UpdateServer addr:%s ", v.ServiceAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,7 +279,7 @@ func (this *Client) ClientConnected(conn net.Conn) (net.Conn, error) {
|
||||
this.connsMapMu.Lock()
|
||||
this.conns[addr] = conn
|
||||
this.connsMapMu.Unlock()
|
||||
this.Debugf("ClientConnected addr:%v", addr)
|
||||
this.options.Log.Debugf("ClientConnected addr:%v", addr)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
@ -275,51 +289,10 @@ func (this *Client) ClientConnectionClose(conn net.Conn) error {
|
||||
this.connsMapMu.Lock()
|
||||
delete(this.conns, addr)
|
||||
this.connsMapMu.Unlock()
|
||||
this.Debugf("ClientConnectionClose addr:%v", addr)
|
||||
this.options.Log.Debugf("ClientConnectionClose addr:%v", addr)
|
||||
return nil
|
||||
}
|
||||
|
||||
///日志***********************************************************************
|
||||
func (this *Client) Debug() bool {
|
||||
return this.options.Debug
|
||||
}
|
||||
|
||||
func (this *Client) Debugf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Debugf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Client) Infof(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Infof("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Client) Warnf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Warnf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Client) Errorf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Errorf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Client) Panicf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Panicf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Client) Fatalf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Fatalf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
//获取目标客户端
|
||||
func (this *Client) getclient(ctx *context.Context, clusterTag string, servicePath string) (c client.XClient, err error) {
|
||||
if servicePath == "" {
|
||||
@ -392,7 +365,7 @@ func (this *Client) registerFunction(servicePath string, fn interface{}, name st
|
||||
}
|
||||
if fname == "" {
|
||||
errorStr := "rpcx.registerFunction: no func name for type " + f.Type().String()
|
||||
this.Errorf(errorStr)
|
||||
this.options.Log.Errorf(errorStr)
|
||||
return fname, errors.New(errorStr)
|
||||
}
|
||||
|
||||
@ -505,7 +478,7 @@ func (this *Client) handleRequest(ctx context.Context, req *protocol.Message) (r
|
||||
} else if replyv != nil {
|
||||
reflectTypePools.Put(mtype.ReplyType, replyv)
|
||||
}
|
||||
this.Debugf("server called service %+v for an request %+v", service, req)
|
||||
this.options.Log.Debugf("server called service %+v for an request %+v", service, req)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ type (
|
||||
ISys interface {
|
||||
Start() (err error)
|
||||
Stop() (err error)
|
||||
GetServiceTags() []string
|
||||
RegisterFunction(fn interface{}) (err error)
|
||||
RegisterFunctionName(name string, fn interface{}) (err error)
|
||||
UnregisterAll() (err error)
|
||||
|
@ -28,7 +28,7 @@ type Options struct {
|
||||
AutoConnect bool //自动连接 客户端启动模式下 主动连接发现的节点服务器
|
||||
SerializeType protocol.SerializeType
|
||||
Debug bool //日志是否开启
|
||||
Log log.ILog
|
||||
Log log.ILogger
|
||||
}
|
||||
|
||||
func SetServiceTag(v string) Option {
|
||||
@ -79,7 +79,7 @@ func SetDebug(v bool) Option {
|
||||
o.Debug = v
|
||||
}
|
||||
}
|
||||
func SetLog(v log.ILog) Option {
|
||||
func SetLog(v log.ILogger) Option {
|
||||
return func(o *Options) {
|
||||
o.Log = v
|
||||
}
|
||||
@ -100,7 +100,7 @@ func newOptions(config map[string]interface{}, opts ...Option) (options *Options
|
||||
return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常")
|
||||
}
|
||||
if options.Debug && options.Log == nil {
|
||||
if options.Log = log.Clone(log.SetLoglayer(2)); options.Log == nil {
|
||||
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.rpc", 2)); options.Log == nil {
|
||||
err = errors.New("log is nil")
|
||||
}
|
||||
}
|
||||
@ -111,8 +111,6 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) {
|
||||
options = &Options{
|
||||
AutoConnect: true,
|
||||
SerializeType: protocol.MsgPack,
|
||||
Debug: true,
|
||||
Log: log.Clone(log.SetLoglayer(2)),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(options)
|
||||
@ -121,7 +119,7 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) {
|
||||
return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常")
|
||||
}
|
||||
if options.Debug && options.Log == nil {
|
||||
if options.Log = log.Clone(log.SetLoglayer(2)); options.Log == nil {
|
||||
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.rpc", 2)); options.Log == nil {
|
||||
err = errors.New("log is nil")
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,10 @@ func (this *RPCX) Stop() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//获取服务集群列表
|
||||
func (this *RPCX) GetServiceTags() []string {
|
||||
return this.GetServiceTags()
|
||||
}
|
||||
func (this *RPCX) RegisterFunction(fn interface{}) (err error) {
|
||||
this.service.RegisterFunction(fn)
|
||||
return
|
||||
|
@ -63,7 +63,7 @@ type Service struct {
|
||||
func (this *Service) Start() (err error) {
|
||||
go func() {
|
||||
if err = this.server.Serve("tcp", this.options.ServiceAddr); err != nil {
|
||||
this.Warnf("rpcx server exit:%v", err)
|
||||
this.options.Log.Warnf("rpcx server exit:%v", err)
|
||||
}
|
||||
}()
|
||||
return
|
||||
@ -75,6 +75,19 @@ func (this *Service) Stop() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//获取服务集群列表
|
||||
func (this *Service) GetServiceTags() []string {
|
||||
this.selectormutex.RLock()
|
||||
tags := make([]string, len(this.selectors))
|
||||
n := 0
|
||||
for k, _ := range this.selectors {
|
||||
tags[n] = k
|
||||
n++
|
||||
}
|
||||
this.selectormutex.RUnlock()
|
||||
return tags
|
||||
}
|
||||
|
||||
//注册RPC 服务
|
||||
func (this *Service) RegisterFunction(fn interface{}) (err error) {
|
||||
err = this.server.RegisterFunction(this.options.ServiceType, fn, this.metadata)
|
||||
@ -204,7 +217,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e
|
||||
ok bool
|
||||
)
|
||||
req_metadata := r.Metadata
|
||||
this.Debugf("PreReadRequest ServicePath:%s ServicePath:%s Metadata:%v ", r.ServicePath, r.ServiceMethod, r.Metadata)
|
||||
this.options.Log.Debugf("PreReadRequest ServicePath:%s ServicePath:%s Metadata:%v ", r.ServicePath, r.ServiceMethod, r.Metadata)
|
||||
if stag, ok = req_metadata[ServiceClusterTag]; ok {
|
||||
this.selectormutex.RLock()
|
||||
selector, ok = this.selectors[stag]
|
||||
@ -228,7 +241,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e
|
||||
}
|
||||
this.clientmutex.Unlock()
|
||||
selector.UpdateServer(servers)
|
||||
this.Debugf("fond new node addr:%s smeta:%s \n", addr, smeta)
|
||||
this.options.Log.Debugf("fond new node addr:%s smeta:%s \n", addr, smeta)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,7 +256,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e
|
||||
this.mutex.Unlock()
|
||||
switch {
|
||||
case call == nil:
|
||||
this.Errorf("callmessage no found call:%d", seq)
|
||||
this.options.Log.Errorf("callmessage no found call:%d", seq)
|
||||
case r.MessageStatusType() == protocol.Error:
|
||||
if len(r.Metadata) > 0 {
|
||||
call.ResMetadata = r.Metadata
|
||||
@ -284,42 +297,6 @@ func (this *Service) RpcxShakeHands(ctx context.Context, args *ServiceNode, repl
|
||||
return nil
|
||||
}
|
||||
|
||||
///日志***********************************************************************
|
||||
func (this *Service) Debug() bool {
|
||||
return this.options.Debug
|
||||
}
|
||||
|
||||
func (this *Service) Debugf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Debugf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Service) Infof(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Infof("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Service) Warnf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Warnf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Service) Errorf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Errorf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Service) Panicf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Panicf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
func (this *Service) Fatalf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.Log.Fatalf("[SYS RPCX] "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
//执行远程调用
|
||||
func (this *Service) call(ctx context.Context, clusterTag string, servicePath string, serviceMethod string, args interface{}, reply interface{}, done chan *client.Call) (conn net.Conn, _call *client.Call, err error) {
|
||||
var (
|
||||
|
@ -3,29 +3,11 @@ package codec
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const host32bit = ^uint(0)>>32 == 0
|
||||
|
||||
type (
|
||||
IDecoder interface {
|
||||
Decoder(buf []byte, v interface{}) error
|
||||
DecoderMap(data map[string][]byte, v interface{}) error
|
||||
DecoderString(buf string, v interface{}) error
|
||||
DecoderMapString(data map[string]string, v interface{}) error
|
||||
DecoderSliceString(data []string, v interface{}) error
|
||||
}
|
||||
IEncoder interface {
|
||||
Encoder(v interface{}) (data []byte, err error)
|
||||
EncoderToMap(v interface{}) (data map[string][]byte, err error)
|
||||
EncoderString(v interface{}) (data string, err error)
|
||||
EncoderToMapString(v interface{}) (data map[string]string, err error)
|
||||
EncoderToSliceString(v interface{}) (data []string, err error)
|
||||
}
|
||||
)
|
||||
|
||||
// string
|
||||
func BytesToString(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
@ -186,31 +168,3 @@ func BytesToBool(buf []byte) bool {
|
||||
var data bool = buf[0] != 0
|
||||
return data
|
||||
}
|
||||
|
||||
func Atoi(b []byte) (int, error) {
|
||||
return strconv.Atoi(BytesToString(b))
|
||||
}
|
||||
|
||||
func ParseInt(b []byte, base int, bitSize int) (int64, error) {
|
||||
return strconv.ParseInt(BytesToString(b), base, bitSize)
|
||||
}
|
||||
|
||||
func ParseUint(b []byte, base int, bitSize int) (uint64, error) {
|
||||
return strconv.ParseUint(BytesToString(b), base, bitSize)
|
||||
}
|
||||
|
||||
func ParseFloat(b []byte, bitSize int) (float64, error) {
|
||||
return strconv.ParseFloat(BytesToString(b), bitSize)
|
||||
}
|
||||
|
||||
func UintToString(n uint64) string {
|
||||
return BytesToString(strconv.AppendUint([]byte{}, n, 10))
|
||||
}
|
||||
|
||||
func IntToString(n int64) string {
|
||||
return BytesToString(strconv.AppendInt([]byte{}, n, 10))
|
||||
}
|
||||
|
||||
func FloatToString(f float64) string {
|
||||
return BytesToString(strconv.AppendFloat([]byte{}, f, 'f', -1, 64))
|
||||
}
|
70
lego/utils/codec/codec.go
Normal file
70
lego/utils/codec/codec.go
Normal file
@ -0,0 +1,70 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
"go_dreamfactory/lego/utils/codec/factory"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
var decoderCache = new(sync.Map)
|
||||
var encoderCache = new(sync.Map)
|
||||
|
||||
func AddDecoder(cacheKey uintptr, decoder codecore.IDecoder) {
|
||||
decoderCache.Store(cacheKey, decoder)
|
||||
}
|
||||
func AddEncoder(cacheKey uintptr, encoder codecore.IEncoder) {
|
||||
encoderCache.Store(cacheKey, encoder)
|
||||
}
|
||||
func GetEncoder(cacheKey uintptr) codecore.IEncoder {
|
||||
encoder, found := encoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return encoder.(codecore.IEncoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func GetDecoder(cacheKey uintptr) codecore.IDecoder {
|
||||
decoder, found := decoderCache.Load(cacheKey)
|
||||
if found {
|
||||
return decoder.(codecore.IDecoder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func EncoderOf(typ reflect2.Type, config *codecore.Config) codecore.IEncoder {
|
||||
cacheKey := typ.RType()
|
||||
encoder := GetEncoder(cacheKey)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
}
|
||||
ctx := &codecore.Ctx{
|
||||
Config: config,
|
||||
Prefix: "",
|
||||
Decoders: map[reflect2.Type]codecore.IDecoder{},
|
||||
Encoders: map[reflect2.Type]codecore.IEncoder{},
|
||||
}
|
||||
encoder = factory.EncoderOfType(ctx, typ)
|
||||
if typ.LikePtr() {
|
||||
encoder = factory.NewonePtrEncoder(encoder)
|
||||
}
|
||||
AddEncoder(cacheKey, encoder)
|
||||
return encoder
|
||||
}
|
||||
func DecoderOf(typ reflect2.Type, config *codecore.Config) codecore.IDecoder {
|
||||
cacheKey := typ.RType()
|
||||
decoder := GetDecoder(cacheKey)
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
}
|
||||
ctx := &codecore.Ctx{
|
||||
Config: config,
|
||||
Prefix: "",
|
||||
Decoders: map[reflect2.Type]codecore.IDecoder{},
|
||||
Encoders: map[reflect2.Type]codecore.IEncoder{},
|
||||
}
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
decoder = factory.DecoderOfType(ctx, ptrType.Elem())
|
||||
AddDecoder(cacheKey, decoder)
|
||||
return decoder
|
||||
}
|
@ -1,65 +1,43 @@
|
||||
package codec
|
||||
package codec_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go_dreamfactory/lego/utils/codec/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestData struct {
|
||||
Fild_1 string
|
||||
Fild_3 int
|
||||
Fild_4 float32
|
||||
Name string
|
||||
Value int
|
||||
Array []interface{}
|
||||
Data map[string]interface{}
|
||||
}
|
||||
type Test1Data struct {
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func Test_Encoder(t *testing.T) {
|
||||
encoder := &Encoder{}
|
||||
// data, err := encoder.EncoderToMap(map[string]interface{}{"liwei": 106, "sasd": "2564"})
|
||||
// fmt.Printf("EncoderToMap data1:%v err:%v", data, err)
|
||||
data, err := encoder.EncoderToMap([]interface{}{"liwei", 106, "sasd", "2564"})
|
||||
fmt.Printf("EncoderToMap data1:%v err:%v", data, err)
|
||||
// data, err := encoder.EncoderToMap(&TestData{Fild_1: "liwei1dao", Fild_3: 25, Fild_4: 3.54})
|
||||
// fmt.Printf("EncoderToMap data2:%v err:%v", data, err)
|
||||
func Test_sys_slice(t *testing.T) {
|
||||
data := []*Test1Data{{"liwe", 1}, {"liwe2", 2}}
|
||||
d, err := json.Marshal(data)
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data = []*Test1Data{}
|
||||
err = json.Unmarshal(d, &data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
}
|
||||
|
||||
func Test_Decoder(t *testing.T) {
|
||||
decoder := &Decoder{}
|
||||
func Test_sys_json(t *testing.T) {
|
||||
d, err := json.Marshal(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data := &TestData{}
|
||||
err := decoder.DecoderMapString(map[string]string{"Fild_1": "liwei1dao"}, data)
|
||||
fmt.Printf("DecoderMap data1:%v err:%v", data, err)
|
||||
err = json.Unmarshal(d, data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
}
|
||||
|
||||
func Test_Slice_Decoder(t *testing.T) {
|
||||
decoder := &Decoder{DefDecoder: json.Unmarshal}
|
||||
encoder := &Encoder{DefEncoder: json.Marshal}
|
||||
data := []*TestData{{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}, {Fild_1: "2dao", Fild_3: 20, Fild_4: 6.5}}
|
||||
datastr, err := encoder.EncoderToSliceString(data)
|
||||
fmt.Printf("EncoderToSliceString datastr:%v err:%v", datastr, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data1 := make([]*TestData, 0)
|
||||
err = decoder.DecoderSliceString(datastr, data1)
|
||||
fmt.Printf("DecoderMap data1:%v err:%v", data1, err)
|
||||
}
|
||||
func Test_sys_mapjson(t *testing.T) {
|
||||
d, err := json.MarshalMap(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
|
||||
fmt.Printf("codec Marshal d:%s err:%v", d, err)
|
||||
data := &TestData{}
|
||||
err = json.UnmarshalMap(d, data)
|
||||
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
|
||||
|
||||
func Test_Slice_Type(t *testing.T) {
|
||||
decoder := &Decoder{DefDecoder: json.Unmarshal}
|
||||
encoder := &Encoder{DefEncoder: json.Marshal}
|
||||
data := []*TestData{{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}, {Fild_1: "2dao", Fild_3: 20, Fild_4: 6.5}}
|
||||
datastr, err := encoder.EncoderToSliceString(data)
|
||||
fmt.Printf("EncoderToSliceString datastr:%v err:%v", datastr, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data1 := make([]*TestData, 0)
|
||||
err = decoder.DecoderSliceString(datastr, &data1)
|
||||
fmt.Printf("DecoderMap data1:%v err:%v", data1, err)
|
||||
}
|
||||
|
||||
func Test_EncoderToMapString(t *testing.T) {
|
||||
encoder := &Encoder{DefEncoder: json.Marshal}
|
||||
data := &TestData{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}
|
||||
_map, err := encoder.EncoderToMapString(data)
|
||||
fmt.Printf("DecoderMap map:%v err:%v", _map, err)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package core
|
||||
package codecore
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@ -7,15 +7,6 @@ import (
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
//数据类型
|
||||
type CodecType int8
|
||||
|
||||
const (
|
||||
Json CodecType = iota //json 格式数据
|
||||
Bytes //byte 字节流数据
|
||||
Proto //proto google protobuff 数据
|
||||
)
|
||||
|
||||
//结构值类型
|
||||
type ValueType int
|
||||
|
||||
@ -37,18 +28,14 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
ICodec interface {
|
||||
Options() *Options
|
||||
GetEncoderFromCache(cacheKey uintptr) IEncoder
|
||||
GetDecoderFromCache(cacheKey uintptr) IDecoder
|
||||
EncoderOf(typ reflect2.Type) IEncoder
|
||||
DecoderOf(typ reflect2.Type) IDecoder
|
||||
BorrowExtractor(buf []byte) IExtractor //借 提取器
|
||||
ReturnExtractor(extra IExtractor) //还 提取器
|
||||
BorrowStream() IStream //借 输出对象
|
||||
ReturnStream(stream IStream) //换 输出对象
|
||||
IPools interface {
|
||||
GetReader(buf []byte) IReader
|
||||
PutReader(w IReader)
|
||||
GetWriter() IWriter
|
||||
PutWriter(w IWriter)
|
||||
}
|
||||
IExtractor interface {
|
||||
IReader interface {
|
||||
IPools
|
||||
ReadVal(obj interface{}) //读取指定类型对象
|
||||
WhatIsNext() ValueType
|
||||
Read() interface{}
|
||||
@ -80,7 +67,8 @@ type (
|
||||
Error() error
|
||||
SetErr(err error)
|
||||
}
|
||||
IStream interface {
|
||||
IWriter interface {
|
||||
IPools
|
||||
WriteVal(val interface{}) //写入一个对象
|
||||
WriteNil() //写空 null
|
||||
WriteEmptyArray() //写空数组 []
|
||||
@ -107,42 +95,36 @@ type (
|
||||
WriteFloat64(val float64)
|
||||
WriteString(val string)
|
||||
WriteBytes(val []byte)
|
||||
Reset(bufSize int)
|
||||
Reset()
|
||||
Buffer() []byte //返回缓存区数据
|
||||
Buffered() int
|
||||
Error() error
|
||||
SetErr(err error)
|
||||
}
|
||||
//Json 编码器
|
||||
IEncoder interface {
|
||||
GetType() reflect.Kind
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
Encode(ptr unsafe.Pointer, stream IStream)
|
||||
}
|
||||
//MapJson 编码器
|
||||
IEncoderMapJson interface {
|
||||
EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error)
|
||||
}
|
||||
//SliceJson 编码器
|
||||
IEncoderSliceJson interface {
|
||||
EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error)
|
||||
}
|
||||
|
||||
//Json 解码器
|
||||
IDecoder interface {
|
||||
GetType() reflect.Kind
|
||||
Decode(ptr unsafe.Pointer, extra IExtractor)
|
||||
Decode(ptr unsafe.Pointer, r IReader)
|
||||
}
|
||||
//MapJson 解码器
|
||||
IDecoderMapJson interface {
|
||||
DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error)
|
||||
DecodeForMapJson(ptr unsafe.Pointer, r IReader, extra map[string]string) (err error)
|
||||
}
|
||||
//MapJson 解码器
|
||||
IDecoderSliceJson interface {
|
||||
DecodeForSliceJson(ptr unsafe.Pointer, extra []string) (err error)
|
||||
DecodeForSliceJson(ptr unsafe.Pointer, r IReader, extra []string) (err error)
|
||||
}
|
||||
//空校验
|
||||
CheckIsEmpty interface {
|
||||
IEncoder interface {
|
||||
GetType() reflect.Kind
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
Encode(ptr unsafe.Pointer, w IWriter)
|
||||
}
|
||||
//MapJson 编码器
|
||||
IEncoderMapJson interface {
|
||||
EncodeToMapJson(ptr unsafe.Pointer, w IWriter) (ret map[string]string, err error)
|
||||
}
|
||||
//SliceJson 编码器
|
||||
IEncoderSliceJson interface {
|
||||
EncodeToSliceJson(ptr unsafe.Pointer, w IWriter) (ret []string, err error)
|
||||
}
|
||||
//内嵌指针是否是空
|
||||
IsEmbeddedPtrNil interface {
|
||||
@ -150,8 +132,17 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
//序列化配置
|
||||
type Config struct {
|
||||
SortMapKeys bool //排序mapkey
|
||||
IndentionStep int //缩进步骤
|
||||
OnlyTaggedField bool //仅仅处理标签字段
|
||||
DisallowUnknownFields bool //禁止未知字段
|
||||
CaseSensitive bool //是否区分大小写
|
||||
TagKey string //标签
|
||||
}
|
||||
type Ctx struct {
|
||||
ICodec
|
||||
Config *Config
|
||||
Prefix string
|
||||
Encoders map[reflect2.Type]IEncoder
|
||||
Decoders map[reflect2.Type]IDecoder
|
||||
@ -159,7 +150,7 @@ type Ctx struct {
|
||||
|
||||
func (this *Ctx) Append(prefix string) *Ctx {
|
||||
return &Ctx{
|
||||
ICodec: this.ICodec,
|
||||
Config: this.Config,
|
||||
Prefix: this.Prefix + " " + prefix,
|
||||
Encoders: this.Encoders,
|
||||
Decoders: this.Decoders,
|
75
lego/utils/codec/compress.go
Normal file
75
lego/utils/codec/compress.go
Normal file
@ -0,0 +1,75 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
spWriter sync.Pool
|
||||
spReader sync.Pool
|
||||
spBuffer sync.Pool
|
||||
)
|
||||
|
||||
func init() {
|
||||
spWriter = sync.Pool{New: func() interface{} {
|
||||
return gzip.NewWriter(nil)
|
||||
}}
|
||||
spReader = sync.Pool{New: func() interface{} {
|
||||
return new(gzip.Reader)
|
||||
}}
|
||||
spBuffer = sync.Pool{New: func() interface{} {
|
||||
return bytes.NewBuffer(nil)
|
||||
}}
|
||||
}
|
||||
|
||||
// Unzip unzips data.
|
||||
func Unzip(data []byte) ([]byte, error) {
|
||||
buf := bytes.NewBuffer(data)
|
||||
|
||||
gr := spReader.Get().(*gzip.Reader)
|
||||
defer func() {
|
||||
spReader.Put(gr)
|
||||
}()
|
||||
err := gr.Reset(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer gr.Close()
|
||||
|
||||
data, err = ioutil.ReadAll(gr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
// Zip zips data.
|
||||
func Zip(data []byte) ([]byte, error) {
|
||||
buf := spBuffer.Get().(*bytes.Buffer)
|
||||
w := spWriter.Get().(*gzip.Writer)
|
||||
w.Reset(buf)
|
||||
|
||||
defer func() {
|
||||
buf.Reset()
|
||||
spBuffer.Put(buf)
|
||||
w.Close()
|
||||
spWriter.Put(w)
|
||||
}()
|
||||
_, err := w.Write(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec := buf.Bytes()
|
||||
return dec, nil
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
//解码器
|
||||
type Decoder struct {
|
||||
DefDecoder func(buf []byte, v interface{}) error //默认编码 扩展自定义编码方式
|
||||
}
|
||||
|
||||
func (this *Decoder) Decoder(buf []byte, v interface{}) error {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
return fmt.Errorf("decoder: Decoder(nil)")
|
||||
case *string:
|
||||
*v = BytesToString(buf)
|
||||
return nil
|
||||
case *[]byte:
|
||||
*v = buf
|
||||
return nil
|
||||
case *int:
|
||||
*v = BytesToInt(buf)
|
||||
return nil
|
||||
case *int8:
|
||||
*v = BytesToInt8(buf)
|
||||
return nil
|
||||
case *int16:
|
||||
*v = BytesToInt16(buf)
|
||||
return nil
|
||||
case *int32:
|
||||
*v = BytesToInt32(buf)
|
||||
return nil
|
||||
case *int64:
|
||||
*v = BytesToInt64(buf)
|
||||
return nil
|
||||
case *uint:
|
||||
*v = BytesToUInt(buf)
|
||||
return nil
|
||||
case *uint8:
|
||||
*v = BytesToUInt8(buf)
|
||||
return nil
|
||||
case *uint16:
|
||||
*v = BytesToUInt16(buf)
|
||||
return nil
|
||||
case *uint32:
|
||||
*v = BytesToUInt32(buf)
|
||||
return nil
|
||||
case *uint64:
|
||||
*v = BytesToUInt64(buf)
|
||||
return nil
|
||||
case *float32:
|
||||
*v = BytesToFloat32(buf)
|
||||
return nil
|
||||
case *float64:
|
||||
*v = BytesToFloat64(buf)
|
||||
return nil
|
||||
case *bool:
|
||||
*v = BytesToBool(buf)
|
||||
return nil
|
||||
case *time.Time:
|
||||
var err error
|
||||
*v, err = time.Parse(time.RFC3339Nano, BytesToString(buf))
|
||||
return err
|
||||
case *time.Duration:
|
||||
*v = time.Duration(BytesToInt64(buf))
|
||||
return nil
|
||||
default:
|
||||
if this.DefDecoder != nil {
|
||||
return this.DefDecoder(buf, v)
|
||||
} else {
|
||||
return fmt.Errorf(
|
||||
"decoder: can't marshal %T (implement decoder.DefDecoder)", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Decoder) DecoderMap(data map[string][]byte, v interface{}) error {
|
||||
vof := reflect.ValueOf(v)
|
||||
if !vof.IsValid() {
|
||||
return fmt.Errorf("Decoder: DecoderMap(nil)")
|
||||
}
|
||||
if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice {
|
||||
return fmt.Errorf("Decoder: DecoderMap(non-pointer %T)", v)
|
||||
}
|
||||
if vof.Kind() == reflect.Map {
|
||||
kt, vt := vof.Type().Key(), vof.Type().Elem()
|
||||
for k, v := range data {
|
||||
key := reflect.New(kt).Elem()
|
||||
if key.Kind() != reflect.Ptr {
|
||||
if err := this.Decoder(StringToBytes(k), key.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err)
|
||||
}
|
||||
} else {
|
||||
if err := this.Decoder(StringToBytes(k), key.Addr()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err)
|
||||
}
|
||||
}
|
||||
value := reflect.New(vt).Elem()
|
||||
if value.Kind() != reflect.Ptr {
|
||||
if err := this.Decoder(v, value.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
} else {
|
||||
value.Interface()
|
||||
if err := this.Decoder(v, value.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
}
|
||||
vof.SetMapIndex(key, value)
|
||||
}
|
||||
} else if vof.Kind() == reflect.Ptr {
|
||||
elem := vof.Elem()
|
||||
relType := elem.Type()
|
||||
for i := 0; i < relType.NumField(); i++ {
|
||||
fieldInfo := relType.Field(i)
|
||||
tag := fieldInfo.Tag
|
||||
name := tag.Get("json")
|
||||
if len(name) == 0 {
|
||||
name = fieldInfo.Name
|
||||
}
|
||||
if value, ok := data[name]; ok {
|
||||
v := reflect.New(fieldInfo.Type).Elem()
|
||||
if fieldInfo.Type.Kind() != reflect.Ptr {
|
||||
if err := this.Decoder(value, v.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
elem.FieldByName(fieldInfo.Name).Set(v)
|
||||
} else {
|
||||
if err := this.Decoder(value, v); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
elem.FieldByName(fieldInfo.Name).Set(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//redis 存储解析 针对 string 转换
|
||||
func (this *Decoder) DecoderString(buf string, v interface{}) (err error) {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
return fmt.Errorf("decoder: Decoder(nil)")
|
||||
case *string:
|
||||
*v = buf
|
||||
return nil
|
||||
case *[]byte:
|
||||
*v = StringToBytes(buf)
|
||||
return nil
|
||||
case *int:
|
||||
*v, err = Atoi(StringToBytes(buf))
|
||||
return
|
||||
case *int8:
|
||||
var n int64
|
||||
n, err = ParseInt(StringToBytes(buf), 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = int8(n)
|
||||
return
|
||||
case *int16:
|
||||
var n int64
|
||||
n, err = ParseInt(StringToBytes(buf), 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = int16(n)
|
||||
return
|
||||
case *int32:
|
||||
var n int64
|
||||
n, err = ParseInt(StringToBytes(buf), 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = int32(n)
|
||||
return
|
||||
case *int64:
|
||||
var n int64
|
||||
n, err = ParseInt(StringToBytes(buf), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = n
|
||||
return
|
||||
case *uint:
|
||||
var n uint64
|
||||
n, err = ParseUint(StringToBytes(buf), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = uint(n)
|
||||
return
|
||||
case *uint8:
|
||||
var n uint64
|
||||
n, err = ParseUint(StringToBytes(buf), 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = uint8(n)
|
||||
return
|
||||
case *uint16:
|
||||
var n uint64
|
||||
n, err = ParseUint(StringToBytes(buf), 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = uint16(n)
|
||||
return
|
||||
case *uint32:
|
||||
var n uint64
|
||||
n, err = ParseUint(StringToBytes(buf), 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = uint32(n)
|
||||
return
|
||||
case *uint64:
|
||||
var n uint64
|
||||
n, err = ParseUint(StringToBytes(buf), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = n
|
||||
return
|
||||
case *float32:
|
||||
var f float64
|
||||
f, err = strconv.ParseFloat(buf, 32)
|
||||
*v = float32(f)
|
||||
return
|
||||
case *float64:
|
||||
*v, err = strconv.ParseFloat(buf, 64)
|
||||
return
|
||||
case *bool:
|
||||
*v, err = strconv.ParseBool(buf)
|
||||
return
|
||||
case *time.Time:
|
||||
var err error
|
||||
*v, err = time.Parse(time.RFC3339Nano, buf)
|
||||
return err
|
||||
case *time.Duration:
|
||||
var n int64
|
||||
n, err = ParseInt(StringToBytes(buf), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*v = time.Duration(n)
|
||||
return
|
||||
default:
|
||||
if this.DefDecoder != nil {
|
||||
return this.DefDecoder(StringToBytes(buf), v)
|
||||
} else {
|
||||
return fmt.Errorf(
|
||||
"decoder: can't marshal %T (implement decoder.DefDecoder)", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//redis 存储解析 针对 string 转换
|
||||
func (this *Decoder) DecoderMapString(data map[string]string, v interface{}) error {
|
||||
vof := reflect.ValueOf(v)
|
||||
if !vof.IsValid() {
|
||||
return fmt.Errorf("Decoder: DecoderMap(nil)")
|
||||
}
|
||||
if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice {
|
||||
return fmt.Errorf("Decoder: DecoderMap(non-pointer %T)", v)
|
||||
}
|
||||
if vof.Kind() == reflect.Map {
|
||||
kt, vt := vof.Type().Key(), vof.Type().Elem()
|
||||
for k, v := range data {
|
||||
key := reflect.New(kt).Elem()
|
||||
if key.Kind() != reflect.Ptr {
|
||||
if err := this.DecoderString(k, key.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err)
|
||||
}
|
||||
} else {
|
||||
if err := this.DecoderString(k, key.Addr()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", key, err)
|
||||
}
|
||||
}
|
||||
value := reflect.New(vt).Elem()
|
||||
if value.Kind() != reflect.Ptr {
|
||||
if err := this.DecoderString(v, value.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
} else {
|
||||
value.Interface()
|
||||
if err := this.DecoderString(v, value.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
}
|
||||
vof.SetMapIndex(key, value)
|
||||
}
|
||||
} else if vof.Kind() == reflect.Ptr {
|
||||
elem := vof.Elem()
|
||||
relType := elem.Type()
|
||||
for i := 0; i < relType.NumField(); i++ {
|
||||
fieldInfo := relType.Field(i)
|
||||
tag := fieldInfo.Tag
|
||||
name := tag.Get("json")
|
||||
if len(name) == 0 {
|
||||
name = fieldInfo.Name
|
||||
}
|
||||
if value, ok := data[name]; ok {
|
||||
v := reflect.New(fieldInfo.Type).Elem()
|
||||
if err := this.DecoderString(value, v.Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("Decoder: Decoder(non-pointer %T) err:%v", value, err)
|
||||
}
|
||||
elem.FieldByName(fieldInfo.Name).Set(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//redis 存储解析 针对 string 转换
|
||||
func (this *Decoder) DecoderSliceString(data []string, v interface{}) error {
|
||||
t := reflect.TypeOf(v)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
if t.Kind() == reflect.Slice {
|
||||
t = t.Elem()
|
||||
} else {
|
||||
panic("Input param is not a slice")
|
||||
}
|
||||
|
||||
sl := reflect.ValueOf(v)
|
||||
|
||||
if t.Kind() == reflect.Ptr {
|
||||
sl = sl.Elem()
|
||||
}
|
||||
|
||||
st := sl.Type()
|
||||
fmt.Printf("Slice Type %s:\n", st)
|
||||
|
||||
sliceType := st.Elem()
|
||||
if sliceType.Kind() == reflect.Ptr {
|
||||
sliceType = sliceType.Elem()
|
||||
}
|
||||
fmt.Printf("Slice Elem Type %v:\n", sliceType)
|
||||
for _, buf := range data {
|
||||
if sl.Len() < sl.Cap() {
|
||||
sl.Set(sl.Slice(0, sl.Len()+1))
|
||||
elem := sl.Index(sl.Len() - 1)
|
||||
if elem.IsNil() {
|
||||
elem.Set(reflect.New(sliceType))
|
||||
}
|
||||
this.DecoderString(buf, elem.Elem().Addr().Interface())
|
||||
continue
|
||||
}
|
||||
elem := reflect.New(sliceType)
|
||||
sl.Set(reflect.Append(sl, elem))
|
||||
this.DecoderString(buf, elem.Elem().Addr().Interface())
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
//编码器
|
||||
type Encoder struct {
|
||||
DefEncoder func(v interface{}) (data []byte, err error) //默认编码 扩展自定义编码方式
|
||||
}
|
||||
|
||||
func (this *Encoder) Encoder(v interface{}) (data []byte, err error) {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
return StringToBytes(""), nil
|
||||
case string:
|
||||
return StringToBytes(v), nil
|
||||
case []byte:
|
||||
return v, nil
|
||||
case int:
|
||||
return IntToBytes(v), nil
|
||||
case int8:
|
||||
return Int8ToBytes(v), nil
|
||||
case int16:
|
||||
return Int16ToBytes(v), nil
|
||||
case int32:
|
||||
return Int32ToBytes(v), nil
|
||||
case int64:
|
||||
return Int64ToBytes(v), nil
|
||||
case uint:
|
||||
return UIntToBytes(v), nil
|
||||
case uint8:
|
||||
return UInt8ToBytes(v), nil
|
||||
case uint16:
|
||||
return UInt16ToBytes(v), nil
|
||||
case uint32:
|
||||
return UInt32ToBytes(v), nil
|
||||
case uint64:
|
||||
return UInt64ToBytes(v), nil
|
||||
case float32:
|
||||
return Float32ToBytes(v), nil
|
||||
case float64:
|
||||
return Float64ToBytes(v), nil
|
||||
case bool:
|
||||
return BoolToBytes(v), nil
|
||||
case time.Time:
|
||||
return v.AppendFormat([]byte{}, time.RFC3339Nano), nil
|
||||
case time.Duration:
|
||||
return Int64ToBytes(v.Nanoseconds()), nil
|
||||
default:
|
||||
if this.DefEncoder != nil {
|
||||
return this.DefEncoder(v)
|
||||
} else {
|
||||
return nil, fmt.Errorf(
|
||||
"encoder: can't marshal %T (implement encoder.DefEncoder)", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Encoder) EncoderToMap(v interface{}) (data map[string][]byte, err error) {
|
||||
vof := reflect.ValueOf(v)
|
||||
if !vof.IsValid() {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(nil)")
|
||||
}
|
||||
if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(non-pointer %T)", v)
|
||||
}
|
||||
// vof = vof.Elem()
|
||||
data = make(map[string][]byte)
|
||||
if vof.Kind() == reflect.Map {
|
||||
keys := vof.MapKeys()
|
||||
for _, k := range keys {
|
||||
value := vof.MapIndex(k)
|
||||
var keydata []byte
|
||||
var valuedata []byte
|
||||
if keydata, err = this.Encoder(k.Interface()); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err)
|
||||
}
|
||||
if valuedata, err = this.Encoder(value.Interface()); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err)
|
||||
}
|
||||
data[BytesToString(keydata)] = valuedata
|
||||
}
|
||||
return
|
||||
} else if vof.Kind() == reflect.Slice {
|
||||
for i := 0; i < vof.Len(); i++ {
|
||||
value := vof.Index(i).Interface()
|
||||
var valuedata []byte
|
||||
if valuedata, err = this.Encoder(value); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value, err)
|
||||
}
|
||||
data[BytesToString(IntToBytes(i))] = valuedata
|
||||
}
|
||||
return
|
||||
} else if vof.Kind() == reflect.Ptr {
|
||||
elem := vof.Elem()
|
||||
relType := elem.Type()
|
||||
for i := 0; i < relType.NumField(); i++ {
|
||||
fieldInfo := relType.Field(i)
|
||||
tag := fieldInfo.Tag
|
||||
name := tag.Get("json")
|
||||
if len(name) == 0 {
|
||||
name = fieldInfo.Name
|
||||
}
|
||||
field := elem.Field(i).Interface()
|
||||
var valuedata []byte
|
||||
if valuedata, err = this.Encoder(field); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", field, err)
|
||||
}
|
||||
data[name] = valuedata
|
||||
}
|
||||
return
|
||||
} else {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T)", v)
|
||||
}
|
||||
}
|
||||
|
||||
//redis 存储编码 针对 string 转换
|
||||
func (this *Encoder) EncoderString(v interface{}) (data string, err error) {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
return "", nil
|
||||
case string:
|
||||
return v, nil
|
||||
case []byte:
|
||||
return BytesToString(v), nil
|
||||
case int:
|
||||
return IntToString(int64(v)), nil
|
||||
case int8:
|
||||
return IntToString(int64(v)), nil
|
||||
case int16:
|
||||
return IntToString(int64(v)), nil
|
||||
case int32:
|
||||
return IntToString(int64(v)), nil
|
||||
case int64:
|
||||
return IntToString(int64(v)), nil
|
||||
case uint:
|
||||
return UintToString(uint64(v)), nil
|
||||
case uint8:
|
||||
return UintToString(uint64(v)), nil
|
||||
case uint16:
|
||||
return UintToString(uint64(v)), nil
|
||||
case uint32:
|
||||
return UintToString(uint64(v)), nil
|
||||
case uint64:
|
||||
return UintToString(uint64(v)), nil
|
||||
case float32:
|
||||
return UintToString(uint64(v)), nil
|
||||
case float64:
|
||||
return UintToString(uint64(v)), nil
|
||||
case bool:
|
||||
if v {
|
||||
return IntToString(1), nil
|
||||
}
|
||||
return IntToString(0), nil
|
||||
case time.Time:
|
||||
return BytesToString(v.AppendFormat([]byte{}, time.RFC3339Nano)), nil
|
||||
case time.Duration:
|
||||
return IntToString(v.Nanoseconds()), nil
|
||||
default:
|
||||
if this.DefEncoder != nil {
|
||||
var b []byte
|
||||
b, err = this.DefEncoder(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return BytesToString(b), nil
|
||||
} else {
|
||||
return "", fmt.Errorf(
|
||||
"encoder: can't marshal %T (implement encoder.DefEncoder)", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//redis 存储编码 针对 string 转换
|
||||
func (this *Encoder) EncoderToMapString(v interface{}) (data map[string]string, err error) {
|
||||
vof := reflect.ValueOf(v)
|
||||
if !vof.IsValid() {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(nil)")
|
||||
}
|
||||
if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(non-pointer %T)", v)
|
||||
}
|
||||
// vof = vof.Elem()
|
||||
data = make(map[string]string)
|
||||
if vof.Kind() == reflect.Map {
|
||||
keys := vof.MapKeys()
|
||||
for _, k := range keys {
|
||||
value := vof.MapIndex(k)
|
||||
var keydata string
|
||||
var valuedata string
|
||||
if keydata, err = this.EncoderString(k.Interface()); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err)
|
||||
}
|
||||
if valuedata, err = this.EncoderString(value.Interface()); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value.Interface(), err)
|
||||
}
|
||||
data[keydata] = valuedata
|
||||
}
|
||||
return
|
||||
} else if vof.Kind() == reflect.Slice {
|
||||
for i := 0; i < vof.Len(); i++ {
|
||||
value := vof.Index(i).Interface()
|
||||
var valuedata string
|
||||
if valuedata, err = this.EncoderString(value); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", value, err)
|
||||
}
|
||||
data[IntToString(int64(i))] = valuedata
|
||||
}
|
||||
return
|
||||
} else if vof.Kind() == reflect.Ptr {
|
||||
elem := vof.Elem()
|
||||
relType := elem.Type()
|
||||
for i := 0; i < relType.NumField(); i++ {
|
||||
fieldInfo := relType.Field(i)
|
||||
tag := fieldInfo.Tag
|
||||
name := tag.Get("json")
|
||||
if len(name) == 0 {
|
||||
continue
|
||||
}
|
||||
field := elem.Field(i).Interface()
|
||||
var valuedata string
|
||||
if valuedata, err = this.EncoderString(field); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T) err:%v", field, err)
|
||||
}
|
||||
data[name] = valuedata
|
||||
}
|
||||
return
|
||||
} else {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToMap(invalid type %T)", v)
|
||||
}
|
||||
}
|
||||
|
||||
//redis 存储编码 针对 string 转换
|
||||
func (this *Encoder) EncoderToSliceString(v interface{}) (data []string, err error) {
|
||||
vof := reflect.ValueOf(v)
|
||||
if !vof.IsValid() {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToSliceString(nil)")
|
||||
}
|
||||
if vof.Kind() != reflect.Ptr && vof.Kind() != reflect.Map && vof.Kind() != reflect.Slice {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToSliceString(non-pointer %T)", v)
|
||||
}
|
||||
// vof = vof.Elem()
|
||||
if vof.Kind() == reflect.Slice {
|
||||
data = make([]string, vof.Len())
|
||||
for i := 0; i < vof.Len(); i++ {
|
||||
value := vof.Index(i).Interface()
|
||||
var valuedata string
|
||||
if valuedata, err = this.EncoderString(value); err != nil {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToSliceString(invalid type %T) err:%v", value, err)
|
||||
}
|
||||
data[i] = valuedata
|
||||
}
|
||||
return
|
||||
} else {
|
||||
return nil, fmt.Errorf("Encoder: EncoderToSliceString(invalid type %T)", v)
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
@ -35,7 +35,7 @@ func (this sortableBindings) Swap(i, j int) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func EncoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
encoder := ctx.Encoders[typ]
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
@ -47,8 +47,8 @@ func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
return encoder
|
||||
}
|
||||
|
||||
func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
var encoder core.IEncoder
|
||||
func _createEncoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
var encoder codecore.IEncoder
|
||||
encoder = createEncoderOfNative(ctx, typ)
|
||||
if encoder != nil {
|
||||
return encoder
|
||||
@ -72,7 +72,7 @@ func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func DecoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
decoder := ctx.Decoders[typ]
|
||||
if decoder != nil {
|
||||
return decoder
|
||||
@ -84,8 +84,8 @@ func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
return decoder
|
||||
}
|
||||
|
||||
func _createDecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
var decoder core.IDecoder
|
||||
func _createDecoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
var decoder codecore.IDecoder
|
||||
|
||||
decoder = createDecoderOfNative(ctx, typ)
|
||||
if decoder != nil {
|
||||
@ -129,25 +129,25 @@ func StringToBytes(s string) []byte {
|
||||
|
||||
//根节点 -------------------------------------------------------------------
|
||||
type rootDecoder struct {
|
||||
decoder core.IDecoder
|
||||
decoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *rootDecoder) GetType() reflect.Kind {
|
||||
return reflect.Ptr
|
||||
}
|
||||
func (this *rootDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
this.decoder.Decode(ptr, extra)
|
||||
func (this *rootDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) {
|
||||
this.decoder.Decode(ptr, r)
|
||||
}
|
||||
|
||||
type rootEncoder struct {
|
||||
encoder core.IEncoder
|
||||
encoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *rootEncoder) GetType() reflect.Kind {
|
||||
return reflect.Ptr
|
||||
}
|
||||
func (this *rootEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
this.encoder.Encode(ptr, stream)
|
||||
func (this *rootEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
|
||||
this.encoder.Encode(ptr, w)
|
||||
}
|
||||
|
||||
func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
@ -155,12 +155,12 @@ func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
//onePtrEncoder---------------------------------------------------------------
|
||||
func NewonePtrEncoder(encoder core.IEncoder) core.IEncoder {
|
||||
func NewonePtrEncoder(encoder codecore.IEncoder) codecore.IEncoder {
|
||||
return &onePtrEncoder{encoder}
|
||||
}
|
||||
|
||||
type onePtrEncoder struct {
|
||||
encoder core.IEncoder
|
||||
encoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *onePtrEncoder) GetType() reflect.Kind {
|
||||
@ -171,16 +171,16 @@ func (this *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return this.encoder.IsEmpty(unsafe.Pointer(&ptr))
|
||||
}
|
||||
|
||||
func (this *onePtrEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *onePtrEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
this.encoder.Encode(unsafe.Pointer(&ptr), stream)
|
||||
}
|
||||
|
||||
func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
|
||||
if encoderMapJson, ok := this.encoder.(core.IEncoderMapJson); !ok {
|
||||
func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
|
||||
if encoderMapJson, ok := this.encoder.(codecore.IEncoderMapJson); !ok {
|
||||
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.encoder)
|
||||
return
|
||||
} else {
|
||||
return encoderMapJson.EncodeToMapJson(unsafe.Pointer(&ptr))
|
||||
return encoderMapJson.EncodeToMapJson(unsafe.Pointer(&ptr), w)
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ type lazyErrorDecoder struct {
|
||||
func (this *lazyErrorDecoder) GetType() reflect.Kind {
|
||||
return reflect.Ptr
|
||||
}
|
||||
func (this *lazyErrorDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *lazyErrorDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if extra.Error() == nil {
|
||||
extra.SetErr(this.err)
|
||||
}
|
||||
@ -206,7 +206,7 @@ func (this *lazyErrorEncoder) GetType() reflect.Kind {
|
||||
return reflect.Ptr
|
||||
}
|
||||
|
||||
func (this *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
if ptr == nil {
|
||||
stream.WriteNil()
|
||||
} else if stream.Error() == nil {
|
@ -7,37 +7,36 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfArray(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
arrayType := typ.(*reflect2.UnsafeArrayType)
|
||||
decoder := DecoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
|
||||
return &arrayDecoder{ctx.ICodec, arrayType, decoder}
|
||||
return &arrayDecoder{arrayType, decoder}
|
||||
}
|
||||
|
||||
func encoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfArray(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
arrayType := typ.(*reflect2.UnsafeArrayType)
|
||||
if arrayType.Len() == 0 {
|
||||
return &emptyArrayEncoder{}
|
||||
}
|
||||
encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
|
||||
return &arrayEncoder{ctx.ICodec, arrayType, encoder}
|
||||
return &arrayEncoder{arrayType, encoder}
|
||||
}
|
||||
|
||||
//array-------------------------------------------------------------------------------------------------------------------------------
|
||||
type arrayEncoder struct {
|
||||
codec core.ICodec
|
||||
arrayType *reflect2.UnsafeArrayType
|
||||
elemEncoder core.IEncoder
|
||||
elemEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (codec *arrayEncoder) GetType() reflect.Kind {
|
||||
return reflect.Array
|
||||
}
|
||||
func (this *arrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *arrayEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteArrayStart()
|
||||
elemPtr := unsafe.Pointer(ptr)
|
||||
this.elemEncoder.Encode(elemPtr, stream)
|
||||
@ -57,32 +56,30 @@ func (this *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
//编码对象到json数组
|
||||
func (this *arrayEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) {
|
||||
func (this *arrayEncoder) EncodeToSliceJson(ptr unsafe.Pointer, w codecore.IWriter) (ret []string, err error) {
|
||||
ret = make([]string, this.arrayType.Len())
|
||||
stream := this.codec.BorrowStream()
|
||||
for i := 1; i < this.arrayType.Len(); i++ {
|
||||
elemPtr := this.arrayType.UnsafeGetIndex(ptr, i)
|
||||
this.elemEncoder.Encode(elemPtr, stream)
|
||||
if stream.Error() != nil && stream.Error() != io.EOF {
|
||||
err = stream.Error()
|
||||
this.elemEncoder.Encode(elemPtr, w)
|
||||
if w.Error() != nil && w.Error() != io.EOF {
|
||||
err = w.Error()
|
||||
return
|
||||
}
|
||||
ret[i] = BytesToString(stream.Buffer())
|
||||
stream.Reset(512)
|
||||
ret[i] = BytesToString(w.Buffer())
|
||||
w.Reset()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type arrayDecoder struct {
|
||||
codec core.ICodec
|
||||
arrayType *reflect2.UnsafeArrayType
|
||||
elemDecoder core.IDecoder
|
||||
elemDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (codec *arrayDecoder) GetType() reflect.Kind {
|
||||
return reflect.Array
|
||||
}
|
||||
func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
arrayType := this.arrayType
|
||||
if extra.ReadNil() {
|
||||
return
|
||||
@ -110,20 +107,19 @@ func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *arrayDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) {
|
||||
func (this *arrayDecoder) DecodeForSliceJson(ptr unsafe.Pointer, r codecore.IReader, data []string) (err error) {
|
||||
arrayType := this.arrayType
|
||||
if data == nil {
|
||||
err = errors.New("extra is nil")
|
||||
return
|
||||
}
|
||||
extra := this.codec.BorrowExtractor([]byte{})
|
||||
arrayType.UnsafeGetIndex(ptr, len(data))
|
||||
for i, v := range data {
|
||||
elemPtr := arrayType.UnsafeGetIndex(ptr, i)
|
||||
extra.ResetBytes(StringToBytes(v))
|
||||
this.elemDecoder.Decode(elemPtr, extra)
|
||||
if extra.Error() != nil && extra.Error() != io.EOF {
|
||||
err = extra.Error()
|
||||
r.ResetBytes(StringToBytes(v))
|
||||
this.elemDecoder.Decode(elemPtr, r)
|
||||
if r.Error() != nil && r.Error() != io.EOF {
|
||||
err = r.Error()
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -136,7 +132,7 @@ func (this *emptyArrayEncoder) GetType() reflect.Kind {
|
||||
return reflect.Array
|
||||
}
|
||||
|
||||
func (this *emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteEmptyArray()
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
@ -17,7 +17,7 @@ type dynamicEncoder struct {
|
||||
func (codec *dynamicEncoder) GetType() reflect.Kind {
|
||||
return reflect.Interface
|
||||
}
|
||||
func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
obj := encoder.valType.UnsafeIndirect(ptr)
|
||||
stream.WriteVal(obj)
|
||||
}
|
||||
@ -32,7 +32,7 @@ type efaceDecoder struct {
|
||||
func (codec *efaceDecoder) GetType() reflect.Kind {
|
||||
return reflect.Interface
|
||||
}
|
||||
func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
pObj := (*interface{})(ptr)
|
||||
obj := *pObj
|
||||
if obj == nil {
|
||||
@ -46,7 +46,7 @@ func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
}
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
ptrElemType := ptrType.Elem()
|
||||
if extra.WhatIsNext() == core.NilValue {
|
||||
if extra.WhatIsNext() == codecore.NilValue {
|
||||
if ptrElemType.Kind() != reflect.Ptr {
|
||||
extra.ReadNil()
|
||||
*pObj = nil
|
||||
@ -69,7 +69,7 @@ type ifaceDecoder struct {
|
||||
func (codec *ifaceDecoder) GetType() reflect.Kind {
|
||||
return reflect.Interface
|
||||
}
|
||||
func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if extra.ReadNil() {
|
||||
decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew())
|
||||
return
|
@ -4,19 +4,19 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfMap(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
mapType := typ.(*reflect2.UnsafeMapType)
|
||||
keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key())
|
||||
elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem())
|
||||
return &mapDecoder{
|
||||
codec: ctx.ICodec,
|
||||
mapType: mapType,
|
||||
keyType: mapType.Key(),
|
||||
elemType: mapType.Elem(),
|
||||
@ -25,17 +25,23 @@ func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
func encoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfMap(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
mapType := typ.(*reflect2.UnsafeMapType)
|
||||
if ctx.Config.SortMapKeys {
|
||||
return &sortKeysMapEncoder{
|
||||
mapType: mapType,
|
||||
keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()),
|
||||
elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()),
|
||||
}
|
||||
}
|
||||
return &mapEncoder{
|
||||
codec: ctx.ICodec,
|
||||
mapType: mapType,
|
||||
keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()),
|
||||
elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
func decoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfMapKey(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return DecoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
|
||||
@ -54,7 +60,7 @@ func decoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfMapKey(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
return EncoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
|
||||
@ -77,17 +83,72 @@ func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
}
|
||||
|
||||
//Map--------------------------------------------------------------------------------------------------------------------------------------
|
||||
type mapEncoder struct {
|
||||
codec core.ICodec
|
||||
type sortKeysMapEncoder struct {
|
||||
mapType *reflect2.UnsafeMapType
|
||||
keyEncoder core.IEncoder
|
||||
elemEncoder core.IEncoder
|
||||
keyEncoder codecore.IEncoder
|
||||
elemEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *sortKeysMapEncoder) GetType() reflect.Kind {
|
||||
return reflect.Map
|
||||
}
|
||||
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
|
||||
if *(*unsafe.Pointer)(ptr) == nil {
|
||||
w.WriteNil()
|
||||
return
|
||||
}
|
||||
w.WriteObjectStart()
|
||||
mapIter := encoder.mapType.UnsafeIterate(ptr)
|
||||
subStream := w.GetWriter()
|
||||
subIter := w.GetReader(nil)
|
||||
keyValues := encodedKeyValues{}
|
||||
for mapIter.HasNext() {
|
||||
key, elem := mapIter.UnsafeNext()
|
||||
subStreamIndex := subStream.Buffered()
|
||||
encoder.keyEncoder.Encode(key, subStream)
|
||||
if subStream.Error() != nil && subStream.Error() != io.EOF && w.Error() == nil {
|
||||
w.SetErr(subStream.Error())
|
||||
}
|
||||
encodedKey := subStream.Buffer()[subStreamIndex:]
|
||||
subIter.ResetBytes(encodedKey)
|
||||
decodedKey := subIter.ReadString()
|
||||
subStream.WriteKVSplit()
|
||||
encoder.elemEncoder.Encode(elem, subStream)
|
||||
keyValues = append(keyValues, encodedKV{
|
||||
key: decodedKey,
|
||||
keyValue: subStream.Buffer()[subStreamIndex:],
|
||||
})
|
||||
}
|
||||
sort.Sort(keyValues)
|
||||
for i, keyValue := range keyValues {
|
||||
if i != 0 {
|
||||
w.WriteMemberSplit()
|
||||
}
|
||||
w.WriteBytes(keyValue.keyValue)
|
||||
}
|
||||
if subStream.Error() != nil && w.Error() == nil {
|
||||
w.SetErr(subStream.Error())
|
||||
}
|
||||
w.WriteObjectEnd()
|
||||
w.PutWriter(subStream)
|
||||
w.PutReader(subIter)
|
||||
}
|
||||
|
||||
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
iter := encoder.mapType.UnsafeIterate(ptr)
|
||||
return !iter.HasNext()
|
||||
}
|
||||
|
||||
type mapEncoder struct {
|
||||
mapType *reflect2.UnsafeMapType
|
||||
keyEncoder codecore.IEncoder
|
||||
elemEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *mapEncoder) GetType() reflect.Kind {
|
||||
return reflect.Map
|
||||
}
|
||||
func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
if *(*unsafe.Pointer)(ptr) == nil {
|
||||
stream.WriteNil()
|
||||
return
|
||||
@ -106,14 +167,17 @@ func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
stream.WriteObjectEnd()
|
||||
}
|
||||
|
||||
func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
|
||||
func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
|
||||
ret = make(map[string]string)
|
||||
var (
|
||||
k, v string
|
||||
)
|
||||
|
||||
keystream := this.codec.BorrowStream()
|
||||
elemstream := this.codec.BorrowStream()
|
||||
keystream := w.GetWriter()
|
||||
elemstream := w.GetWriter()
|
||||
defer func() {
|
||||
w.PutWriter(keystream)
|
||||
w.PutWriter(elemstream)
|
||||
}()
|
||||
iter := this.mapType.UnsafeIterate(ptr)
|
||||
for i := 0; iter.HasNext(); i++ {
|
||||
key, elem := iter.UnsafeNext()
|
||||
@ -138,8 +202,8 @@ func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]stri
|
||||
v = *((*string)(elem))
|
||||
}
|
||||
ret[k] = v
|
||||
keystream.Reset(512)
|
||||
elemstream.Reset(512)
|
||||
keystream.Reset()
|
||||
elemstream.Reset()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -150,18 +214,17 @@ func (this *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
type mapDecoder struct {
|
||||
codec core.ICodec
|
||||
mapType *reflect2.UnsafeMapType
|
||||
keyType reflect2.Type
|
||||
elemType reflect2.Type
|
||||
keyDecoder core.IDecoder
|
||||
elemDecoder core.IDecoder
|
||||
keyDecoder codecore.IDecoder
|
||||
elemDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (codec *mapDecoder) GetType() reflect.Kind {
|
||||
return reflect.Map
|
||||
}
|
||||
func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
mapType := this.mapType
|
||||
if extra.ReadNil() {
|
||||
*(*unsafe.Pointer)(ptr) = nil
|
||||
@ -200,9 +263,13 @@ func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
}
|
||||
|
||||
//解码对象从MapJson 中
|
||||
func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) {
|
||||
keyext := this.codec.BorrowExtractor([]byte{})
|
||||
elemext := this.codec.BorrowExtractor([]byte{})
|
||||
func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) {
|
||||
keyext := r.GetReader([]byte{})
|
||||
elemext := r.GetReader([]byte{})
|
||||
defer func() {
|
||||
r.PutReader(keyext)
|
||||
r.PutReader(keyext)
|
||||
}()
|
||||
for k, v := range extra {
|
||||
key := this.keyType.UnsafeNew()
|
||||
if this.keyDecoder.GetType() != reflect.String {
|
||||
@ -233,13 +300,13 @@ func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]st
|
||||
|
||||
//NumericMap-------------------------------------------------------------------------------------------------------------------------------
|
||||
type numericMapKeyDecoder struct {
|
||||
decoder core.IDecoder
|
||||
decoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *numericMapKeyDecoder) GetType() reflect.Kind {
|
||||
return this.decoder.GetType()
|
||||
}
|
||||
func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadKeyStart() {
|
||||
return
|
||||
}
|
||||
@ -250,13 +317,13 @@ func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtract
|
||||
}
|
||||
|
||||
type numericMapKeyEncoder struct {
|
||||
encoder core.IEncoder
|
||||
encoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *numericMapKeyEncoder) GetType() reflect.Kind {
|
||||
return this.encoder.GetType()
|
||||
}
|
||||
func (this *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteKeyStart()
|
||||
this.encoder.Encode(ptr, stream)
|
||||
stream.WriteKeyEnd()
|
||||
@ -268,7 +335,7 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
type dynamicMapKeyEncoder struct {
|
||||
ctx *core.Ctx
|
||||
ctx *codecore.Ctx
|
||||
valType reflect2.Type
|
||||
}
|
||||
|
||||
@ -276,7 +343,7 @@ func (this *dynamicMapKeyEncoder) GetType() reflect.Kind {
|
||||
return reflect.Interface
|
||||
}
|
||||
|
||||
func (this *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
obj := this.valType.UnsafeIndirect(ptr)
|
||||
encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
|
||||
}
|
||||
@ -285,3 +352,14 @@ func (this *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
obj := this.valType.UnsafeIndirect(ptr)
|
||||
return encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
|
||||
}
|
||||
|
||||
type encodedKeyValues []encodedKV
|
||||
|
||||
type encodedKV struct {
|
||||
key string
|
||||
keyValue []byte
|
||||
}
|
||||
|
||||
func (sv encodedKeyValues) Len() int { return len(sv) }
|
||||
func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
||||
func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }
|
@ -5,14 +5,14 @@ import (
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
const ptrSize = 32 << uintptr(^uintptr(0)>>63) //计算int的大小 是32 还是64
|
||||
|
||||
func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func createDecoderOfNative(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
typeName := typ.String()
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
@ -103,7 +103,7 @@ func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createEncoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func createEncoderOfNative(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
typeName := typ.String()
|
||||
kind := typ.Kind()
|
||||
switch kind {
|
||||
@ -201,11 +201,11 @@ type stringCodec struct {
|
||||
func (codec *stringCodec) GetType() reflect.Kind {
|
||||
return reflect.String
|
||||
}
|
||||
func (codec *stringCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *stringCodec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
*((*string)(ptr)) = extra.ReadString()
|
||||
}
|
||||
|
||||
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
str := *((*string)(ptr))
|
||||
stream.WriteString(str)
|
||||
}
|
||||
@ -221,13 +221,13 @@ func (codec *int8Codec) GetType() reflect.Kind {
|
||||
return reflect.Int8
|
||||
}
|
||||
|
||||
func (codec *int8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *int8Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*int8)(ptr)) = extra.ReadInt8()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteInt8(*((*int8)(ptr)))
|
||||
}
|
||||
|
||||
@ -241,13 +241,13 @@ type int16Codec struct {
|
||||
func (codec *int16Codec) GetType() reflect.Kind {
|
||||
return reflect.Int16
|
||||
}
|
||||
func (codec *int16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *int16Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*int16)(ptr)) = extra.ReadInt16()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteInt16(*((*int16)(ptr)))
|
||||
}
|
||||
|
||||
@ -261,13 +261,13 @@ type int32Codec struct {
|
||||
func (codec *int32Codec) GetType() reflect.Kind {
|
||||
return reflect.Int32
|
||||
}
|
||||
func (codec *int32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *int32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*int32)(ptr)) = extra.ReadInt32()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteInt32(*((*int32)(ptr)))
|
||||
}
|
||||
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
@ -280,13 +280,13 @@ type int64Codec struct {
|
||||
func (codec *int64Codec) GetType() reflect.Kind {
|
||||
return reflect.Int64
|
||||
}
|
||||
func (codec *int64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *int64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*int64)(ptr)) = extra.ReadInt64()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteInt64(*((*int64)(ptr)))
|
||||
}
|
||||
|
||||
@ -300,13 +300,13 @@ type uint8Codec struct {
|
||||
func (codec *uint8Codec) GetType() reflect.Kind {
|
||||
return reflect.Uint8
|
||||
}
|
||||
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*uint8)(ptr)) = extra.ReadUint8()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteUint8(*((*uint8)(ptr)))
|
||||
}
|
||||
|
||||
@ -320,13 +320,13 @@ type uint16Codec struct {
|
||||
func (codec *uint16Codec) GetType() reflect.Kind {
|
||||
return reflect.Uint16
|
||||
}
|
||||
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*uint16)(ptr)) = extra.ReadUint16()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteUint16(*((*uint16)(ptr)))
|
||||
}
|
||||
|
||||
@ -340,13 +340,13 @@ type uint32Codec struct {
|
||||
func (codec *uint32Codec) GetType() reflect.Kind {
|
||||
return reflect.Uint32
|
||||
}
|
||||
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*uint32)(ptr)) = extra.ReadUint32()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteUint32(*((*uint32)(ptr)))
|
||||
}
|
||||
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
@ -359,13 +359,13 @@ type uint64Codec struct {
|
||||
func (codec *uint64Codec) GetType() reflect.Kind {
|
||||
return reflect.Uint64
|
||||
}
|
||||
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*uint64)(ptr)) = extra.ReadUint64()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteUint64(*((*uint64)(ptr)))
|
||||
}
|
||||
|
||||
@ -379,13 +379,13 @@ type float32Codec struct {
|
||||
func (codec *float32Codec) GetType() reflect.Kind {
|
||||
return reflect.Float32
|
||||
}
|
||||
func (codec *float32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *float32Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*float32)(ptr)) = extra.ReadFloat32()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteFloat32(*((*float32)(ptr)))
|
||||
}
|
||||
|
||||
@ -399,13 +399,13 @@ type float64Codec struct {
|
||||
func (codec *float64Codec) GetType() reflect.Kind {
|
||||
return reflect.Float64
|
||||
}
|
||||
func (codec *float64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *float64Codec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*float64)(ptr)) = extra.ReadFloat64()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteFloat64(*((*float64)(ptr)))
|
||||
}
|
||||
|
||||
@ -419,13 +419,13 @@ type boolCodec struct {
|
||||
func (codec *boolCodec) GetType() reflect.Kind {
|
||||
return reflect.Bool
|
||||
}
|
||||
func (codec *boolCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (codec *boolCodec) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if !extra.ReadNil() {
|
||||
*((*bool)(ptr)) = extra.ReadBool()
|
||||
}
|
||||
}
|
||||
|
||||
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteBool(*((*bool)(ptr)))
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfOptional(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
elemType := ptrType.Elem()
|
||||
decoder := DecoderOfType(ctx, elemType)
|
||||
return &OptionalDecoder{elemType, decoder}
|
||||
}
|
||||
|
||||
func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfOptional(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
ptrType := typ.(*reflect2.UnsafePtrType)
|
||||
elemType := ptrType.Elem()
|
||||
elemEncoder := EncoderOfType(ctx, elemType)
|
||||
@ -28,13 +28,13 @@ func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
//Optional--------------------------------------------------------------------------------------------------------------------
|
||||
type OptionalDecoder struct {
|
||||
ValueType reflect2.Type
|
||||
ValueDecoder core.IDecoder
|
||||
ValueDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *OptionalDecoder) GetType() reflect.Kind {
|
||||
return this.ValueDecoder.GetType()
|
||||
}
|
||||
func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if extra.ReadNil() {
|
||||
*((*unsafe.Pointer)(ptr)) = nil
|
||||
} else {
|
||||
@ -48,23 +48,23 @@ func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *OptionalDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) {
|
||||
if decoderMapJson, ok := this.ValueDecoder.(core.IDecoderMapJson); !ok {
|
||||
func (this *OptionalDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) {
|
||||
if decoderMapJson, ok := this.ValueDecoder.(codecore.IDecoderMapJson); !ok {
|
||||
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueDecoder)
|
||||
return
|
||||
} else {
|
||||
return decoderMapJson.DecodeForMapJson(ptr, extra)
|
||||
return decoderMapJson.DecodeForMapJson(ptr, r, extra)
|
||||
}
|
||||
}
|
||||
|
||||
type OptionalEncoder struct {
|
||||
ValueEncoder core.IEncoder
|
||||
ValueEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *OptionalEncoder) GetType() reflect.Kind {
|
||||
return this.ValueEncoder.GetType()
|
||||
}
|
||||
func (this *OptionalEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *OptionalEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
stream.WriteNil()
|
||||
} else {
|
||||
@ -76,8 +76,8 @@ func (this *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*unsafe.Pointer)(ptr)) == nil
|
||||
}
|
||||
|
||||
func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
|
||||
if encoderMapJson, ok := this.ValueEncoder.(core.IEncoderMapJson); !ok {
|
||||
func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
|
||||
if encoderMapJson, ok := this.ValueEncoder.(codecore.IEncoderMapJson); !ok {
|
||||
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueEncoder)
|
||||
return
|
||||
} else {
|
||||
@ -85,17 +85,17 @@ func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string
|
||||
err = fmt.Errorf("encoder ptr is nil")
|
||||
return
|
||||
} else {
|
||||
return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr)))
|
||||
return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr)), w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//reference--------------------------------------------------------------------------------------------------------------------
|
||||
type referenceEncoder struct {
|
||||
encoder core.IEncoder
|
||||
encoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *referenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *referenceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
this.encoder.Encode(unsafe.Pointer(&ptr), stream)
|
||||
}
|
||||
|
||||
@ -104,23 +104,23 @@ func (this *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
type referenceDecoder struct {
|
||||
decoder core.IDecoder
|
||||
decoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *referenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *referenceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
this.decoder.Decode(unsafe.Pointer(&ptr), extra)
|
||||
}
|
||||
|
||||
//dereference--------------------------------------------------------------------------------------------------------------------
|
||||
type dereferenceDecoder struct {
|
||||
valueType reflect2.Type
|
||||
valueDecoder core.IDecoder
|
||||
valueDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *dereferenceDecoder) GetType() reflect.Kind {
|
||||
return this.valueDecoder.GetType()
|
||||
}
|
||||
func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
newPtr := this.valueType.UnsafeNew()
|
||||
this.valueDecoder.Decode(newPtr, extra)
|
||||
@ -131,13 +131,13 @@ func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor
|
||||
}
|
||||
|
||||
type dereferenceEncoder struct {
|
||||
ValueEncoder core.IEncoder
|
||||
ValueEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (this *dereferenceEncoder) GetType() reflect.Kind {
|
||||
return this.ValueEncoder.GetType()
|
||||
}
|
||||
func (this *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
stream.WriteNil()
|
||||
} else {
|
||||
@ -158,7 +158,7 @@ func (this *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
|
||||
if deReferenced == nil {
|
||||
return true
|
||||
}
|
||||
isEmbeddedPtrNil, converted := this.ValueEncoder.(core.IsEmbeddedPtrNil)
|
||||
isEmbeddedPtrNil, converted := this.ValueEncoder.(codecore.IsEmbeddedPtrNil)
|
||||
if !converted {
|
||||
return false
|
||||
}
|
@ -7,32 +7,31 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func decoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfSlice(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
sliceType := typ.(*reflect2.UnsafeSliceType)
|
||||
decoder := DecoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
|
||||
return &sliceDecoder{ctx.ICodec, sliceType, decoder}
|
||||
return &sliceDecoder{sliceType, decoder}
|
||||
}
|
||||
func encoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfSlice(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
sliceType := typ.(*reflect2.UnsafeSliceType)
|
||||
encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
|
||||
return &sliceEncoder{ctx.ICodec, sliceType, encoder}
|
||||
return &sliceEncoder{sliceType, encoder}
|
||||
}
|
||||
|
||||
type sliceEncoder struct {
|
||||
codec core.ICodec
|
||||
sliceType *reflect2.UnsafeSliceType
|
||||
elemEncoder core.IEncoder
|
||||
elemEncoder codecore.IEncoder
|
||||
}
|
||||
|
||||
func (codec *sliceEncoder) GetType() reflect.Kind {
|
||||
return reflect.Slice
|
||||
}
|
||||
func (this *sliceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *sliceEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
if this.sliceType.UnsafeIsNil(ptr) {
|
||||
stream.WriteNil()
|
||||
return
|
||||
@ -60,7 +59,7 @@ func (this *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
//编码对象到json数组
|
||||
func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) {
|
||||
func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer, w codecore.IWriter) (ret []string, err error) {
|
||||
if this.sliceType.UnsafeIsNil(ptr) {
|
||||
err = errors.New("val is nil")
|
||||
return
|
||||
@ -70,30 +69,28 @@ func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, e
|
||||
if length == 0 {
|
||||
return
|
||||
}
|
||||
stream := this.codec.BorrowStream()
|
||||
for i := 1; i < length; i++ {
|
||||
elemPtr := this.sliceType.UnsafeGetIndex(ptr, i)
|
||||
this.elemEncoder.Encode(elemPtr, stream)
|
||||
if stream.Error() != nil && stream.Error() != io.EOF {
|
||||
err = stream.Error()
|
||||
this.elemEncoder.Encode(elemPtr, w)
|
||||
if w.Error() != nil && w.Error() != io.EOF {
|
||||
err = w.Error()
|
||||
return
|
||||
}
|
||||
ret[i] = BytesToString(stream.Buffer())
|
||||
stream.Reset(512)
|
||||
ret[i] = BytesToString(w.Buffer())
|
||||
w.Reset()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type sliceDecoder struct {
|
||||
codec core.ICodec
|
||||
sliceType *reflect2.UnsafeSliceType
|
||||
elemDecoder core.IDecoder
|
||||
elemDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (codec *sliceDecoder) GetType() reflect.Kind {
|
||||
return reflect.Slice
|
||||
}
|
||||
func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra codecore.IReader) {
|
||||
sliceType := this.sliceType
|
||||
if extra.ReadNil() {
|
||||
sliceType.UnsafeSetNil(ptr)
|
||||
@ -125,20 +122,19 @@ func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *sliceDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) {
|
||||
func (this *sliceDecoder) DecodeForSliceJson(ptr unsafe.Pointer, r codecore.IReader, data []string) (err error) {
|
||||
sliceType := this.sliceType
|
||||
if data == nil {
|
||||
err = errors.New("extra is nil")
|
||||
return
|
||||
}
|
||||
extra := this.codec.BorrowExtractor([]byte{})
|
||||
sliceType.UnsafeGrow(ptr, len(data))
|
||||
for i, v := range data {
|
||||
elemPtr := sliceType.UnsafeGetIndex(ptr, i)
|
||||
extra.ResetBytes(StringToBytes(v))
|
||||
this.elemDecoder.Decode(elemPtr, extra)
|
||||
if extra.Error() != nil && extra.Error() != io.EOF {
|
||||
err = extra.Error()
|
||||
r.ResetBytes(StringToBytes(v))
|
||||
this.elemDecoder.Decode(elemPtr, r)
|
||||
if r.Error() != nil && r.Error() != io.EOF {
|
||||
err = r.Error()
|
||||
return
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import (
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
@ -25,11 +25,11 @@ type Binding struct {
|
||||
Field reflect2.StructField
|
||||
FromNames []string
|
||||
ToNames []string
|
||||
Encoder core.IEncoder
|
||||
Decoder core.IDecoder
|
||||
Encoder codecore.IEncoder
|
||||
Decoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
func encoderOfStruct(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
|
||||
type bindingTo struct {
|
||||
binding *Binding
|
||||
toName string
|
||||
@ -47,7 +47,7 @@ func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
if old.toName != toName {
|
||||
continue
|
||||
}
|
||||
old.ignored, new.ignored = resolveConflictBinding(ctx.Options(), old.binding, new.binding)
|
||||
old.ignored, new.ignored = resolveConflictBinding(ctx.Config, old.binding, new.binding)
|
||||
}
|
||||
orderedBindings = append(orderedBindings, new)
|
||||
}
|
||||
@ -64,10 +64,10 @@ func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
|
||||
})
|
||||
}
|
||||
}
|
||||
return &structEncoder{ctx.ICodec, typ, finalOrderedFields}
|
||||
return &structEncoder{typ, finalOrderedFields}
|
||||
}
|
||||
|
||||
func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
func decoderOfStruct(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
|
||||
bindings := map[string]*Binding{}
|
||||
structDescriptor := describeStruct(ctx, typ)
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
@ -77,7 +77,7 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
bindings[fromName] = binding
|
||||
continue
|
||||
}
|
||||
ignoreOld, ignoreNew := resolveConflictBinding(ctx.Options(), old, binding)
|
||||
ignoreOld, ignoreNew := resolveConflictBinding(ctx.Config, old, binding)
|
||||
if ignoreOld {
|
||||
delete(bindings, fromName)
|
||||
}
|
||||
@ -91,25 +91,25 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
|
||||
fields[k] = binding.Decoder.(*structFieldDecoder)
|
||||
}
|
||||
|
||||
if !ctx.Options().CaseSensitive {
|
||||
if !ctx.Config.CaseSensitive {
|
||||
for k, binding := range bindings {
|
||||
if _, found := fields[strings.ToLower(k)]; !found {
|
||||
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
|
||||
}
|
||||
}
|
||||
}
|
||||
return createStructDecoder(ctx.ICodec, typ, fields)
|
||||
return &structDecoder{ctx.Config, typ, fields}
|
||||
}
|
||||
|
||||
//结构第编辑码构建
|
||||
func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor {
|
||||
func describeStruct(ctx *codecore.Ctx, typ reflect2.Type) *StructDescriptor {
|
||||
structType := typ.(*reflect2.UnsafeStructType)
|
||||
embeddedBindings := []*Binding{}
|
||||
bindings := []*Binding{}
|
||||
for i := 0; i < structType.NumField(); i++ {
|
||||
field := structType.Field(i)
|
||||
tag, hastag := field.Tag().Lookup(ctx.Options().TagKey)
|
||||
if ctx.Options().OnlyTaggedField && !hastag && !field.Anonymous() {
|
||||
tag, hastag := field.Tag().Lookup(ctx.Config.TagKey)
|
||||
if ctx.Config.OnlyTaggedField && !hastag && !field.Anonymous() {
|
||||
continue
|
||||
}
|
||||
if tag == "-" || field.Name() == "_" {
|
||||
@ -160,22 +160,22 @@ func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor {
|
||||
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
|
||||
}
|
||||
|
||||
func createStructDescriptor(ctx *core.Ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
|
||||
func createStructDescriptor(ctx *codecore.Ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
|
||||
structDescriptor := &StructDescriptor{
|
||||
Type: typ,
|
||||
Fields: bindings,
|
||||
}
|
||||
processTags(structDescriptor, ctx.ICodec)
|
||||
processTags(structDescriptor, ctx.Config)
|
||||
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
|
||||
sort.Sort(allBindings)
|
||||
structDescriptor.Fields = allBindings
|
||||
return structDescriptor
|
||||
}
|
||||
|
||||
func processTags(structDescriptor *StructDescriptor, codec core.ICodec) {
|
||||
func processTags(structDescriptor *StructDescriptor, config *codecore.Config) {
|
||||
for _, binding := range structDescriptor.Fields {
|
||||
shouldOmitEmpty := false
|
||||
tagParts := strings.Split(binding.Field.Tag().Get(codec.Options().TagKey), ",")
|
||||
tagParts := strings.Split(binding.Field.Tag().Get(config.TagKey), ",")
|
||||
for _, tagPart := range tagParts[1:] {
|
||||
if tagPart == "omitempty" {
|
||||
shouldOmitEmpty = true
|
||||
@ -206,17 +206,9 @@ func calcFieldNames(originalFieldName string, tagProvidedFieldName string, whole
|
||||
return fieldNames
|
||||
}
|
||||
|
||||
func createStructDecoder(codec core.ICodec, typ reflect2.Type, fields map[string]*structFieldDecoder) core.IDecoder {
|
||||
if codec.Options().DisallowUnknownFields {
|
||||
return &structDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
|
||||
} else {
|
||||
return &structDecoder{codec, typ, fields, false}
|
||||
}
|
||||
}
|
||||
|
||||
func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ignoreNew bool) {
|
||||
newTagged := new.Field.Tag().Get(opt.TagKey) != ""
|
||||
oldTagged := old.Field.Tag().Get(opt.TagKey) != ""
|
||||
func resolveConflictBinding(config *codecore.Config, old, new *Binding) (ignoreOld, ignoreNew bool) {
|
||||
newTagged := new.Field.Tag().Get(config.TagKey) != ""
|
||||
oldTagged := old.Field.Tag().Get(config.TagKey) != ""
|
||||
if newTagged {
|
||||
if oldTagged {
|
||||
if len(old.levels) > len(new.levels) {
|
||||
@ -245,7 +237,6 @@ func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ig
|
||||
|
||||
//结构对象 编解码-----------------------------------------------------------------------------------------------------------------------
|
||||
type structEncoder struct {
|
||||
codec core.ICodec
|
||||
typ reflect2.Type
|
||||
fields []structFieldTo
|
||||
}
|
||||
@ -253,7 +244,7 @@ type structEncoder struct {
|
||||
func (codec *structEncoder) GetType() reflect.Kind {
|
||||
return reflect.Struct
|
||||
}
|
||||
func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (this *structEncoder) Encode(ptr unsafe.Pointer, stream codecore.IWriter) {
|
||||
stream.WriteObjectStart()
|
||||
isNotFirst := false
|
||||
for _, field := range this.fields {
|
||||
@ -276,9 +267,8 @@ func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
|
||||
func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
|
||||
ret = make(map[string]string)
|
||||
stream := this.codec.BorrowStream()
|
||||
for _, field := range this.fields {
|
||||
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
|
||||
continue
|
||||
@ -286,13 +276,13 @@ func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]s
|
||||
if field.encoder.IsEmbeddedPtrNil(ptr) {
|
||||
continue
|
||||
}
|
||||
stream.Reset(512)
|
||||
field.encoder.Encode(ptr, stream)
|
||||
if stream.Error() != nil && stream.Error() != io.EOF {
|
||||
err = stream.Error()
|
||||
w.Reset()
|
||||
field.encoder.Encode(ptr, w)
|
||||
if w.Error() != nil && w.Error() != io.EOF {
|
||||
err = w.Error()
|
||||
return
|
||||
}
|
||||
ret[field.toName] = BytesToString(stream.Buffer())
|
||||
ret[field.toName] = BytesToString(w.Buffer())
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -302,68 +292,67 @@ func (this *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
type structDecoder struct {
|
||||
codec core.ICodec
|
||||
typ reflect2.Type
|
||||
fields map[string]*structFieldDecoder
|
||||
disallowUnknownFields bool
|
||||
config *codecore.Config
|
||||
typ reflect2.Type
|
||||
fields map[string]*structFieldDecoder
|
||||
}
|
||||
|
||||
func (codec *structDecoder) GetType() reflect.Kind {
|
||||
return reflect.Struct
|
||||
}
|
||||
func (this *structDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
if !extra.ReadObjectStart() {
|
||||
func (this *structDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) {
|
||||
if !r.ReadObjectStart() {
|
||||
return
|
||||
}
|
||||
this.decodeField(ptr, extra)
|
||||
for extra.ReadMemberSplit() {
|
||||
this.decodeField(ptr, extra)
|
||||
this.decodeField(ptr, r)
|
||||
for r.ReadMemberSplit() {
|
||||
this.decodeField(ptr, r)
|
||||
}
|
||||
if extra.Error() != nil && extra.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 {
|
||||
extra.SetErr(fmt.Errorf("%v.%s", this.typ, extra.Error().Error()))
|
||||
if r.Error() != nil && r.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 {
|
||||
r.SetErr(fmt.Errorf("%v.%s", this.typ, r.Error().Error()))
|
||||
}
|
||||
extra.ReadObjectEnd()
|
||||
r.ReadObjectEnd()
|
||||
}
|
||||
|
||||
func (this *structDecoder) decodeField(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (this *structDecoder) decodeField(ptr unsafe.Pointer, r codecore.IReader) {
|
||||
var field string
|
||||
var fieldDecoder *structFieldDecoder
|
||||
|
||||
field = extra.ReadString()
|
||||
field = r.ReadString()
|
||||
fieldDecoder = this.fields[field]
|
||||
if fieldDecoder == nil && !this.codec.Options().CaseSensitive {
|
||||
if fieldDecoder == nil && !this.config.CaseSensitive {
|
||||
fieldDecoder = this.fields[strings.ToLower(field)]
|
||||
}
|
||||
|
||||
if fieldDecoder == nil {
|
||||
if this.disallowUnknownFields {
|
||||
if this.config.DisallowUnknownFields {
|
||||
msg := "found unknown field: " + field
|
||||
extra.SetErr(fmt.Errorf("decodeField %s", msg))
|
||||
r.SetErr(fmt.Errorf("decodeField %s", msg))
|
||||
return
|
||||
}
|
||||
if !extra.ReadKVSplit() {
|
||||
if !r.ReadKVSplit() {
|
||||
return
|
||||
}
|
||||
extra.Skip() //跳过一个数据单元
|
||||
r.Skip() //跳过一个数据单元
|
||||
return
|
||||
}
|
||||
if !extra.ReadKVSplit() {
|
||||
if !r.ReadKVSplit() {
|
||||
return
|
||||
}
|
||||
fieldDecoder.Decode(ptr, extra)
|
||||
fieldDecoder.Decode(ptr, r)
|
||||
}
|
||||
|
||||
//解码对象从MapJson 中
|
||||
func (this *structDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) {
|
||||
func (this *structDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) {
|
||||
var fieldDecoder *structFieldDecoder
|
||||
ext := this.codec.BorrowExtractor([]byte{})
|
||||
ext := r.GetReader([]byte{})
|
||||
for k, v := range extra {
|
||||
fieldDecoder = this.fields[k]
|
||||
if fieldDecoder == nil && !this.codec.Options().CaseSensitive {
|
||||
if fieldDecoder == nil && !this.config.CaseSensitive {
|
||||
fieldDecoder = this.fields[strings.ToLower(k)]
|
||||
}
|
||||
if fieldDecoder == nil {
|
||||
if this.disallowUnknownFields {
|
||||
if this.config.DisallowUnknownFields {
|
||||
err = errors.New("found unknown field: " + k)
|
||||
return
|
||||
}
|
||||
@ -386,18 +375,18 @@ type structFieldTo struct {
|
||||
}
|
||||
type structFieldEncoder struct {
|
||||
field reflect2.StructField
|
||||
fieldEncoder core.IEncoder
|
||||
fieldEncoder codecore.IEncoder
|
||||
omitempty bool
|
||||
}
|
||||
|
||||
func (this *structFieldEncoder) GetType() reflect.Kind {
|
||||
return this.fieldEncoder.GetType()
|
||||
}
|
||||
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
|
||||
fieldPtr := encoder.field.UnsafeGet(ptr)
|
||||
encoder.fieldEncoder.Encode(fieldPtr, stream)
|
||||
if stream.Error() != nil && stream.Error() != io.EOF {
|
||||
stream.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error().Error()))
|
||||
encoder.fieldEncoder.Encode(fieldPtr, w)
|
||||
if w.Error() != nil && w.Error() != io.EOF {
|
||||
w.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), w.Error().Error()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +396,7 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
}
|
||||
|
||||
func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
|
||||
isEmbeddedPtrNil, converted := encoder.fieldEncoder.(core.IsEmbeddedPtrNil)
|
||||
isEmbeddedPtrNil, converted := encoder.fieldEncoder.(codecore.IsEmbeddedPtrNil)
|
||||
if !converted {
|
||||
return false
|
||||
}
|
||||
@ -417,17 +406,17 @@ func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
|
||||
|
||||
type structFieldDecoder struct {
|
||||
field reflect2.StructField
|
||||
fieldDecoder core.IDecoder
|
||||
fieldDecoder codecore.IDecoder
|
||||
}
|
||||
|
||||
func (this *structFieldDecoder) GetType() reflect.Kind {
|
||||
return this.fieldDecoder.GetType()
|
||||
}
|
||||
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
|
||||
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) {
|
||||
fieldPtr := decoder.field.UnsafeGet(ptr)
|
||||
decoder.fieldDecoder.Decode(fieldPtr, extra)
|
||||
if extra.Error() != nil && extra.Error() != io.EOF {
|
||||
extra.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), extra.Error().Error()))
|
||||
decoder.fieldDecoder.Decode(fieldPtr, r)
|
||||
if r.Error() != nil && r.Error() != io.EOF {
|
||||
r.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), r.Error().Error()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,8 +427,8 @@ type emptyStructEncoder struct {
|
||||
func (codec *emptyStructEncoder) GetType() reflect.Kind {
|
||||
return reflect.Struct
|
||||
}
|
||||
func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
|
||||
stream.WriteEmptyObject()
|
||||
func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
|
||||
w.WriteEmptyObject()
|
||||
}
|
||||
|
||||
func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
221
lego/utils/codec/json/core.go
Normal file
221
lego/utils/codec/json/core.go
Normal file
@ -0,0 +1,221 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"go_dreamfactory/lego/utils/codec"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
const defsize = 512
|
||||
|
||||
var writerPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &JsonWriter{
|
||||
buf: make([]byte, 0, defsize),
|
||||
err: nil,
|
||||
indention: 0,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func GetReader(buf []byte) codecore.IReader {
|
||||
reader := readerPool.Get().(codecore.IReader)
|
||||
reader.ResetBytes(buf)
|
||||
return reader
|
||||
}
|
||||
|
||||
func PutReader(r codecore.IReader) {
|
||||
readerPool.Put(r)
|
||||
}
|
||||
|
||||
var readerPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &JsonReader{
|
||||
buf: nil,
|
||||
head: 0,
|
||||
tail: 0,
|
||||
depth: 0,
|
||||
err: nil,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func GetWriter() codecore.IWriter {
|
||||
writer := writerPool.Get().(codecore.IWriter)
|
||||
return writer
|
||||
}
|
||||
|
||||
func PutWriter(w codecore.IWriter) {
|
||||
writerPool.Put(w)
|
||||
}
|
||||
|
||||
const maxDepth = 10000
|
||||
|
||||
var hexDigits []byte
|
||||
var valueTypes []codecore.ValueType
|
||||
|
||||
func init() {
|
||||
hexDigits = make([]byte, 256)
|
||||
for i := 0; i < len(hexDigits); i++ {
|
||||
hexDigits[i] = 255
|
||||
}
|
||||
for i := '0'; i <= '9'; i++ {
|
||||
hexDigits[i] = byte(i - '0')
|
||||
}
|
||||
for i := 'a'; i <= 'f'; i++ {
|
||||
hexDigits[i] = byte((i - 'a') + 10)
|
||||
}
|
||||
for i := 'A'; i <= 'F'; i++ {
|
||||
hexDigits[i] = byte((i - 'A') + 10)
|
||||
}
|
||||
valueTypes = make([]codecore.ValueType, 256)
|
||||
for i := 0; i < len(valueTypes); i++ {
|
||||
valueTypes[i] = codecore.InvalidValue
|
||||
}
|
||||
valueTypes['"'] = codecore.StringValue
|
||||
valueTypes['-'] = codecore.NumberValue
|
||||
valueTypes['0'] = codecore.NumberValue
|
||||
valueTypes['1'] = codecore.NumberValue
|
||||
valueTypes['2'] = codecore.NumberValue
|
||||
valueTypes['3'] = codecore.NumberValue
|
||||
valueTypes['4'] = codecore.NumberValue
|
||||
valueTypes['5'] = codecore.NumberValue
|
||||
valueTypes['6'] = codecore.NumberValue
|
||||
valueTypes['7'] = codecore.NumberValue
|
||||
valueTypes['8'] = codecore.NumberValue
|
||||
valueTypes['9'] = codecore.NumberValue
|
||||
valueTypes['t'] = codecore.BoolValue
|
||||
valueTypes['f'] = codecore.BoolValue
|
||||
valueTypes['n'] = codecore.NilValue
|
||||
valueTypes['['] = codecore.ArrayValue
|
||||
valueTypes['{'] = codecore.ObjectValue
|
||||
}
|
||||
|
||||
var defconf = &codecore.Config{
|
||||
SortMapKeys: true,
|
||||
IndentionStep: 1,
|
||||
OnlyTaggedField: false,
|
||||
DisallowUnknownFields: false,
|
||||
CaseSensitive: false,
|
||||
TagKey: "json",
|
||||
}
|
||||
|
||||
func Marshal(val interface{}) (buf []byte, err error) {
|
||||
writer := GetWriter()
|
||||
defer PutWriter(writer)
|
||||
writer.WriteVal(val)
|
||||
if writer.Error() != nil {
|
||||
return nil, writer.Error()
|
||||
}
|
||||
result := writer.Buffer()
|
||||
copied := make([]byte, len(result))
|
||||
copy(copied, result)
|
||||
return copied, nil
|
||||
}
|
||||
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
extra := GetReader(data)
|
||||
defer PutReader(extra)
|
||||
extra.ReadVal(v)
|
||||
return extra.Error()
|
||||
}
|
||||
|
||||
func MarshalMap(val interface{}) (ret map[string]string, err error) {
|
||||
if nil == val {
|
||||
err = errors.New("val is null")
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := codec.GetEncoder(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = codec.EncoderOf(typ, defconf)
|
||||
}
|
||||
if encoderMapJson, ok := encoder.(codecore.IEncoderMapJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
w := GetWriter()
|
||||
ret, err = encoderMapJson.EncodeToMapJson(reflect2.PtrOf(val), w)
|
||||
PutWriter(w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UnmarshalMap(data map[string]string, val interface{}) (err error) {
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
decoder := codec.GetDecoder(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
if typ == nil || typ.Kind() != reflect.Ptr {
|
||||
err = errors.New("can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = codec.DecoderOf(typ, defconf)
|
||||
}
|
||||
ptr := reflect2.PtrOf(val)
|
||||
if ptr == nil {
|
||||
err = errors.New("can not read into nil pointer")
|
||||
return
|
||||
}
|
||||
if decoderMapJson, ok := decoder.(codecore.IDecoderMapJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
r := GetReader([]byte{})
|
||||
err = decoderMapJson.DecodeForMapJson(ptr, r, data)
|
||||
PutReader(r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func MarshalSlice(val interface{}) (ret []string, err error) {
|
||||
if nil == val {
|
||||
err = errors.New("val is null")
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := codec.GetEncoder(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = codec.EncoderOf(typ, defconf)
|
||||
}
|
||||
if encoderMapJson, ok := encoder.(codecore.IEncoderSliceJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
|
||||
} else {
|
||||
w := GetWriter()
|
||||
ret, err = encoderMapJson.EncodeToSliceJson(reflect2.PtrOf(val), w)
|
||||
w.PutWriter(w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UnmarshalSlice(data []string, val interface{}) (err error) {
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
decoder := codec.GetDecoder(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
if typ == nil || typ.Kind() != reflect.Ptr {
|
||||
err = errors.New("can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = codec.DecoderOf(typ, defconf)
|
||||
}
|
||||
ptr := reflect2.PtrOf(val)
|
||||
if ptr == nil {
|
||||
err = errors.New("can not read into nil pointer")
|
||||
return
|
||||
}
|
||||
if decoderMapJson, ok := decoder.(codecore.IDecoderSliceJson); !ok {
|
||||
err = fmt.Errorf("val type:%T not support UnmarshalSliceJson", val)
|
||||
} else {
|
||||
r := GetReader([]byte{})
|
||||
err = decoderMapJson.DecodeForSliceJson(ptr, r, data)
|
||||
PutReader(r)
|
||||
}
|
||||
return
|
||||
}
|
@ -1,30 +1,21 @@
|
||||
package render
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/sys/codec/utils"
|
||||
|
||||
"io"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"unicode/utf16"
|
||||
|
||||
"go_dreamfactory/lego/utils/codec"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
"go_dreamfactory/lego/utils/codec/utils"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func NewExtractor(codec core.ICodec) *JsonExtractor {
|
||||
return &JsonExtractor{
|
||||
codec: codec,
|
||||
buf: nil,
|
||||
head: 0,
|
||||
tail: 0,
|
||||
depth: 0,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
type JsonExtractor struct {
|
||||
codec core.ICodec
|
||||
type JsonReader struct {
|
||||
buf []byte
|
||||
head int
|
||||
tail int
|
||||
@ -32,17 +23,29 @@ type JsonExtractor struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (this *JsonExtractor) ReadVal(obj interface{}) {
|
||||
func (this *JsonReader) GetReader(buf []byte) codecore.IReader {
|
||||
return GetReader(buf)
|
||||
}
|
||||
func (this *JsonReader) PutReader(r codecore.IReader) {
|
||||
PutReader(r)
|
||||
}
|
||||
func (this *JsonReader) GetWriter() codecore.IWriter {
|
||||
return GetWriter()
|
||||
}
|
||||
func (this *JsonReader) PutWriter(w codecore.IWriter) {
|
||||
PutWriter(w)
|
||||
}
|
||||
func (this *JsonReader) ReadVal(obj interface{}) {
|
||||
depth := this.depth
|
||||
cacheKey := reflect2.RTypeOf(obj)
|
||||
decoder := this.codec.GetDecoderFromCache(cacheKey)
|
||||
decoder := codec.GetDecoder(cacheKey)
|
||||
if decoder == nil {
|
||||
typ := reflect2.TypeOf(obj)
|
||||
if typ == nil || typ.Kind() != reflect.Ptr {
|
||||
this.reportError("ReadVal", "can only unmarshal into pointer")
|
||||
return
|
||||
}
|
||||
decoder = this.codec.DecoderOf(typ)
|
||||
decoder = codec.DecoderOf(typ, defconf)
|
||||
}
|
||||
ptr := reflect2.PtrOf(obj)
|
||||
if ptr == nil {
|
||||
@ -55,35 +58,35 @@ func (this *JsonExtractor) ReadVal(obj interface{}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) WhatIsNext() core.ValueType {
|
||||
func (this *JsonReader) WhatIsNext() codecore.ValueType {
|
||||
valueType := valueTypes[this.nextToken()]
|
||||
this.unreadByte()
|
||||
return valueType
|
||||
}
|
||||
func (this *JsonExtractor) Read() interface{} {
|
||||
func (this *JsonReader) Read() interface{} {
|
||||
valueType := this.WhatIsNext()
|
||||
switch valueType {
|
||||
case core.StringValue:
|
||||
case codecore.StringValue:
|
||||
return this.ReadString()
|
||||
case core.NumberValue:
|
||||
case codecore.NumberValue:
|
||||
return this.ReadFloat64()
|
||||
case core.NilValue:
|
||||
case codecore.NilValue:
|
||||
this.skipFourBytes('n', 'u', 'l', 'l')
|
||||
return nil
|
||||
case core.BoolValue:
|
||||
case codecore.BoolValue:
|
||||
return this.ReadBool()
|
||||
case core.ArrayValue:
|
||||
case codecore.ArrayValue:
|
||||
arr := []interface{}{}
|
||||
this.ReadArrayCB(func(extra core.IExtractor) bool {
|
||||
this.ReadArrayCB(func(extra codecore.IReader) bool {
|
||||
var elem interface{}
|
||||
extra.ReadVal(&elem)
|
||||
arr = append(arr, elem)
|
||||
return true
|
||||
})
|
||||
return arr
|
||||
case core.ObjectValue:
|
||||
case codecore.ObjectValue:
|
||||
obj := map[string]interface{}{}
|
||||
this.ReadMapCB(func(extra core.IExtractor, field string) bool {
|
||||
this.ReadMapCB(func(extra codecore.IReader, field string) bool {
|
||||
var elem interface{}
|
||||
this.ReadVal(&elem)
|
||||
obj[field] = elem
|
||||
@ -95,7 +98,7 @@ func (this *JsonExtractor) Read() interface{} {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) ReadNil() (ret bool) {
|
||||
func (this *JsonReader) ReadNil() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == 'n' {
|
||||
this.skipThreeBytes('u', 'l', 'l') // null
|
||||
@ -104,7 +107,7 @@ func (this *JsonExtractor) ReadNil() (ret bool) {
|
||||
this.unreadByte()
|
||||
return false
|
||||
}
|
||||
func (this *JsonExtractor) ReadArrayStart() (ret bool) {
|
||||
func (this *JsonReader) ReadArrayStart() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == '[' {
|
||||
return true
|
||||
@ -112,7 +115,7 @@ func (this *JsonExtractor) ReadArrayStart() (ret bool) {
|
||||
this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) {
|
||||
func (this *JsonReader) CheckNextIsArrayEnd() (ret bool) {
|
||||
c := this.nextToken()
|
||||
this.unreadByte()
|
||||
if c == ']' {
|
||||
@ -120,7 +123,7 @@ func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadArrayEnd() (ret bool) {
|
||||
func (this *JsonReader) ReadArrayEnd() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == ']' {
|
||||
return true
|
||||
@ -128,7 +131,7 @@ func (this *JsonExtractor) ReadArrayEnd() (ret bool) {
|
||||
this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadObjectStart() (ret bool) {
|
||||
func (this *JsonReader) ReadObjectStart() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == '{' {
|
||||
return this.incrementDepth()
|
||||
@ -136,7 +139,7 @@ func (this *JsonExtractor) ReadObjectStart() (ret bool) {
|
||||
this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) {
|
||||
func (this *JsonReader) CheckNextIsObjectEnd() (ret bool) {
|
||||
c := this.nextToken()
|
||||
this.unreadByte()
|
||||
if c == '}' {
|
||||
@ -144,7 +147,7 @@ func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadObjectEnd() (ret bool) {
|
||||
func (this *JsonReader) ReadObjectEnd() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == '}' {
|
||||
return this.decrementDepth()
|
||||
@ -152,7 +155,7 @@ func (this *JsonExtractor) ReadObjectEnd() (ret bool) {
|
||||
this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadMemberSplit() (ret bool) {
|
||||
func (this *JsonReader) ReadMemberSplit() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == ',' {
|
||||
return true
|
||||
@ -160,7 +163,7 @@ func (this *JsonExtractor) ReadMemberSplit() (ret bool) {
|
||||
this.unreadByte()
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadKVSplit() (ret bool) {
|
||||
func (this *JsonReader) ReadKVSplit() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == ':' {
|
||||
return true
|
||||
@ -168,7 +171,7 @@ func (this *JsonExtractor) ReadKVSplit() (ret bool) {
|
||||
this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadKeyStart() (ret bool) {
|
||||
func (this *JsonReader) ReadKeyStart() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == '"' {
|
||||
return true
|
||||
@ -176,7 +179,7 @@ func (this *JsonExtractor) ReadKeyStart() (ret bool) {
|
||||
this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadKeyEnd() (ret bool) {
|
||||
func (this *JsonReader) ReadKeyEnd() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == '"' {
|
||||
return true
|
||||
@ -184,7 +187,7 @@ func (this *JsonExtractor) ReadKeyEnd() (ret bool) {
|
||||
this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) Skip() {
|
||||
func (this *JsonReader) Skip() {
|
||||
c := this.nextToken()
|
||||
switch c {
|
||||
case '"':
|
||||
@ -209,7 +212,7 @@ func (this *JsonExtractor) Skip() {
|
||||
return
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) ReadBool() (ret bool) {
|
||||
func (this *JsonReader) ReadBool() (ret bool) {
|
||||
c := this.nextToken()
|
||||
if c == 't' {
|
||||
this.skipThreeBytes('r', 'u', 'e')
|
||||
@ -222,7 +225,7 @@ func (this *JsonExtractor) ReadBool() (ret bool) {
|
||||
this.reportError("ReadBool", "expect t or f, but found "+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadInt8() (ret int8) {
|
||||
func (this *JsonReader) ReadInt8() (ret int8) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -234,7 +237,7 @@ func (this *JsonExtractor) ReadInt8() (ret int8) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadInt16() (ret int16) {
|
||||
func (this *JsonReader) ReadInt16() (ret int16) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -246,7 +249,7 @@ func (this *JsonExtractor) ReadInt16() (ret int16) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadInt32() (ret int32) {
|
||||
func (this *JsonReader) ReadInt32() (ret int32) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -258,7 +261,7 @@ func (this *JsonExtractor) ReadInt32() (ret int32) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadInt64() (ret int64) {
|
||||
func (this *JsonReader) ReadInt64() (ret int64) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -270,7 +273,7 @@ func (this *JsonExtractor) ReadInt64() (ret int64) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadUint8() (ret uint8) {
|
||||
func (this *JsonReader) ReadUint8() (ret uint8) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -282,7 +285,7 @@ func (this *JsonExtractor) ReadUint8() (ret uint8) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadUint16() (ret uint16) {
|
||||
func (this *JsonReader) ReadUint16() (ret uint16) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -294,7 +297,7 @@ func (this *JsonExtractor) ReadUint16() (ret uint16) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadUint32() (ret uint32) {
|
||||
func (this *JsonReader) ReadUint32() (ret uint32) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -306,7 +309,7 @@ func (this *JsonExtractor) ReadUint32() (ret uint32) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadUint64() (ret uint64) {
|
||||
func (this *JsonReader) ReadUint64() (ret uint64) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -318,7 +321,7 @@ func (this *JsonExtractor) ReadUint64() (ret uint64) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadFloat32() (ret float32) {
|
||||
func (this *JsonReader) ReadFloat32() (ret float32) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -330,7 +333,7 @@ func (this *JsonExtractor) ReadFloat32() (ret float32) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadFloat64() (ret float64) {
|
||||
func (this *JsonReader) ReadFloat64() (ret float64) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -342,7 +345,7 @@ func (this *JsonExtractor) ReadFloat64() (ret float64) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ReadString() (ret string) {
|
||||
func (this *JsonReader) ReadString() (ret string) {
|
||||
c := this.nextToken()
|
||||
if c == '"' {
|
||||
for i := this.head; i < this.tail; i++ {
|
||||
@ -367,20 +370,20 @@ func (this *JsonExtractor) ReadString() (ret string) {
|
||||
this.reportError("ReadString", `expects " or n, but found `+string([]byte{c}))
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) ResetBytes(d []byte) {
|
||||
func (this *JsonReader) ResetBytes(d []byte) {
|
||||
this.buf = d
|
||||
this.head = 0
|
||||
this.tail = len(d)
|
||||
}
|
||||
func (this *JsonExtractor) Error() error {
|
||||
func (this *JsonReader) Error() error {
|
||||
return this.err
|
||||
}
|
||||
func (this *JsonExtractor) SetErr(err error) {
|
||||
func (this *JsonReader) SetErr(err error) {
|
||||
this.err = err
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------------
|
||||
func (this *JsonExtractor) readByte() (ret byte) {
|
||||
func (this *JsonReader) readByte() (ret byte) {
|
||||
if this.head == this.tail {
|
||||
return 0
|
||||
}
|
||||
@ -388,7 +391,7 @@ func (this *JsonExtractor) readByte() (ret byte) {
|
||||
this.head++
|
||||
return ret
|
||||
}
|
||||
func (this *JsonExtractor) readStringSlowPath() (ret string) {
|
||||
func (this *JsonReader) readStringSlowPath() (ret string) {
|
||||
var str []byte
|
||||
var c byte
|
||||
for this.err == nil {
|
||||
@ -406,7 +409,7 @@ func (this *JsonExtractor) readStringSlowPath() (ret string) {
|
||||
this.reportError("readStringSlowPath", "unexpected end of input")
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte {
|
||||
func (this *JsonReader) readEscapedChar(c byte, str []byte) []byte {
|
||||
switch c {
|
||||
case 'u':
|
||||
r := this.readU4()
|
||||
@ -465,7 +468,7 @@ func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte {
|
||||
}
|
||||
return str
|
||||
}
|
||||
func (this *JsonExtractor) readU4() (ret rune) {
|
||||
func (this *JsonReader) readU4() (ret rune) {
|
||||
for i := 0; i < 4; i++ {
|
||||
c := this.readByte()
|
||||
if this.err != nil {
|
||||
@ -484,7 +487,7 @@ func (this *JsonExtractor) readU4() (ret rune) {
|
||||
}
|
||||
return ret
|
||||
}
|
||||
func (this *JsonExtractor) nextToken() byte {
|
||||
func (this *JsonReader) nextToken() byte {
|
||||
for i := this.head; i < this.tail; i++ {
|
||||
c := this.buf[i]
|
||||
switch c {
|
||||
@ -496,14 +499,14 @@ func (this *JsonExtractor) nextToken() byte {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func (this *JsonExtractor) unreadByte() {
|
||||
func (this *JsonReader) unreadByte() {
|
||||
if this.err != nil {
|
||||
return
|
||||
}
|
||||
this.head--
|
||||
return
|
||||
}
|
||||
func (this *JsonExtractor) skipNumber() {
|
||||
func (this *JsonReader) skipNumber() {
|
||||
if !this.trySkipNumber() {
|
||||
this.unreadByte()
|
||||
if this.err != nil && this.err != io.EOF {
|
||||
@ -516,7 +519,7 @@ func (this *JsonExtractor) skipNumber() {
|
||||
}
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) {
|
||||
func (this *JsonReader) ReadBigFloat() (ret *big.Float) {
|
||||
var (
|
||||
n int
|
||||
err error
|
||||
@ -528,7 +531,7 @@ func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) {
|
||||
this.head += n
|
||||
return
|
||||
}
|
||||
func (iter *JsonExtractor) trySkipNumber() bool {
|
||||
func (iter *JsonReader) trySkipNumber() bool {
|
||||
dotFound := false
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
c := iter.buf[i]
|
||||
@ -564,13 +567,13 @@ func (iter *JsonExtractor) trySkipNumber() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (this *JsonExtractor) skipString() {
|
||||
func (this *JsonReader) skipString() {
|
||||
if !this.trySkipString() {
|
||||
this.unreadByte()
|
||||
this.ReadString()
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) trySkipString() bool {
|
||||
func (this *JsonReader) trySkipString() bool {
|
||||
for i := this.head; i < this.tail; i++ {
|
||||
c := this.buf[i]
|
||||
if c == '"' {
|
||||
@ -586,21 +589,21 @@ func (this *JsonExtractor) trySkipString() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (this *JsonExtractor) skipObject() {
|
||||
func (this *JsonReader) skipObject() {
|
||||
this.unreadByte()
|
||||
this.ReadObjectCB(func(extra core.IExtractor, field string) bool {
|
||||
this.ReadObjectCB(func(extra codecore.IReader, field string) bool {
|
||||
extra.Skip()
|
||||
return true
|
||||
})
|
||||
}
|
||||
func (this *JsonExtractor) skipArray() {
|
||||
func (this *JsonReader) skipArray() {
|
||||
this.unreadByte()
|
||||
this.ReadArrayCB(func(extra core.IExtractor) bool {
|
||||
this.ReadArrayCB(func(extra codecore.IReader) bool {
|
||||
extra.Skip()
|
||||
return true
|
||||
})
|
||||
}
|
||||
func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) {
|
||||
func (this *JsonReader) skipThreeBytes(b1, b2, b3 byte) {
|
||||
if this.readByte() != b1 {
|
||||
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
|
||||
return
|
||||
@ -614,7 +617,7 @@ func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) {
|
||||
return
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) {
|
||||
func (this *JsonReader) skipFourBytes(b1, b2, b3, b4 byte) {
|
||||
if this.readByte() != b1 {
|
||||
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
|
||||
return
|
||||
@ -632,7 +635,7 @@ func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) {
|
||||
return
|
||||
}
|
||||
}
|
||||
func (this *JsonExtractor) reportError(operation string, msg string) {
|
||||
func (this *JsonReader) reportError(operation string, msg string) {
|
||||
if this.err != nil {
|
||||
if this.err != io.EOF {
|
||||
return
|
||||
@ -659,7 +662,7 @@ func (this *JsonExtractor) reportError(operation string, msg string) {
|
||||
this.err = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
|
||||
operation, msg, this.head-peekStart, parsing, context)
|
||||
}
|
||||
func (this *JsonExtractor) incrementDepth() (success bool) {
|
||||
func (this *JsonReader) incrementDepth() (success bool) {
|
||||
this.depth++
|
||||
if this.depth <= maxDepth {
|
||||
return true
|
||||
@ -667,7 +670,7 @@ func (this *JsonExtractor) incrementDepth() (success bool) {
|
||||
this.reportError("incrementDepth", "exceeded max depth")
|
||||
return false
|
||||
}
|
||||
func (this *JsonExtractor) decrementDepth() (success bool) {
|
||||
func (this *JsonReader) decrementDepth() (success bool) {
|
||||
this.depth--
|
||||
if this.depth >= 0 {
|
||||
return true
|
||||
@ -675,7 +678,7 @@ func (this *JsonExtractor) decrementDepth() (success bool) {
|
||||
this.reportError("decrementDepth", "unexpected negative nesting")
|
||||
return false
|
||||
}
|
||||
func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) bool) bool {
|
||||
func (iter *JsonReader) ReadObjectCB(callback func(codecore.IReader, string) bool) bool {
|
||||
c := iter.nextToken()
|
||||
var field string
|
||||
if c == '{' {
|
||||
@ -729,7 +732,7 @@ func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) b
|
||||
return false
|
||||
}
|
||||
|
||||
func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool) bool {
|
||||
func (iter *JsonReader) ReadMapCB(callback func(codecore.IReader, string) bool) bool {
|
||||
c := iter.nextToken()
|
||||
if c == '{' {
|
||||
if !iter.incrementDepth() {
|
||||
@ -784,7 +787,7 @@ func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool
|
||||
return false
|
||||
}
|
||||
|
||||
func (iter *JsonExtractor) ReadArrayCB(callback func(core.IExtractor) bool) (ret bool) {
|
||||
func (iter *JsonReader) ReadArrayCB(callback func(codecore.IReader) bool) (ret bool) {
|
||||
c := iter.nextToken()
|
||||
if c == '[' {
|
||||
if !iter.incrementDepth() {
|
216
lego/utils/codec/json/writer.go
Normal file
216
lego/utils/codec/json/writer.go
Normal file
@ -0,0 +1,216 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"go_dreamfactory/lego/utils/codec"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
"go_dreamfactory/lego/utils/codec/utils"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
const indentionStep = 1
|
||||
|
||||
type JsonWriter struct {
|
||||
err error
|
||||
buf []byte
|
||||
indention int
|
||||
}
|
||||
|
||||
func (this *JsonWriter) GetReader(buf []byte) codecore.IReader {
|
||||
return GetReader(buf)
|
||||
}
|
||||
func (this *JsonWriter) PutReader(r codecore.IReader) {
|
||||
PutReader(r)
|
||||
}
|
||||
func (this *JsonWriter) GetWriter() codecore.IWriter {
|
||||
return GetWriter()
|
||||
}
|
||||
func (this *JsonWriter) PutWriter(w codecore.IWriter) {
|
||||
PutWriter(w)
|
||||
}
|
||||
|
||||
//写入对象
|
||||
func (this *JsonWriter) WriteVal(val interface{}) {
|
||||
if nil == val {
|
||||
this.WriteNil()
|
||||
return
|
||||
}
|
||||
cacheKey := reflect2.RTypeOf(val)
|
||||
encoder := codec.GetEncoder(cacheKey)
|
||||
if encoder == nil {
|
||||
typ := reflect2.TypeOf(val)
|
||||
encoder = codec.EncoderOf(typ, defconf)
|
||||
}
|
||||
encoder.Encode(reflect2.PtrOf(val), this)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) WriteNil() {
|
||||
this.writeFourBytes('n', 'u', 'l', 'l')
|
||||
}
|
||||
func (this *JsonWriter) WriteEmptyArray() {
|
||||
this.writeTwoBytes('[', ']')
|
||||
}
|
||||
func (this *JsonWriter) WriteArrayStart() {
|
||||
this.indention += indentionStep
|
||||
this.writeByte('[')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonWriter) WriteArrayEnd() {
|
||||
this.writeIndention(indentionStep)
|
||||
this.indention -= indentionStep
|
||||
this.writeByte(']')
|
||||
}
|
||||
func (this *JsonWriter) WriteEmptyObject() {
|
||||
this.writeTwoBytes('{', '}')
|
||||
}
|
||||
func (this *JsonWriter) WriteObjectStart() {
|
||||
this.indention += indentionStep
|
||||
this.writeByte('{')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonWriter) WriteObjectEnd() {
|
||||
this.writeIndention(indentionStep)
|
||||
this.indention -= indentionStep
|
||||
this.writeByte('}')
|
||||
}
|
||||
func (this *JsonWriter) WriteMemberSplit() {
|
||||
this.writeByte(',')
|
||||
this.writeIndention(0)
|
||||
}
|
||||
func (this *JsonWriter) WriteKVSplit() {
|
||||
this.writeByte(':')
|
||||
}
|
||||
func (this *JsonWriter) WriteKeyStart() {
|
||||
this.writeByte('"')
|
||||
}
|
||||
func (this *JsonWriter) WriteKeyEnd() {
|
||||
this.writeByte('"')
|
||||
}
|
||||
func (this *JsonWriter) WriteObjectFieldName(val string) {
|
||||
this.WriteString(val)
|
||||
if this.indention > 0 {
|
||||
this.writeTwoBytes(':', ' ')
|
||||
} else {
|
||||
this.writeByte(':')
|
||||
}
|
||||
}
|
||||
func (this *JsonWriter) WriteBool(val bool) {
|
||||
if val {
|
||||
this.writeTrue()
|
||||
} else {
|
||||
this.writeFalse()
|
||||
}
|
||||
}
|
||||
func (this *JsonWriter) WriteInt8(val int8) {
|
||||
utils.WriteInt8ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteInt16(val int16) {
|
||||
utils.WriteInt16ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteInt32(val int32) {
|
||||
utils.WriteInt32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteInt64(val int64) {
|
||||
utils.WriteInt64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteUint8(val uint8) {
|
||||
utils.WriteUint8ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteUint16(val uint16) {
|
||||
utils.WriteUint16ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteUint32(val uint32) {
|
||||
utils.WriteUint32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteUint64(val uint64) {
|
||||
utils.WriteUint64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteFloat32(val float32) {
|
||||
utils.WriteFloat32ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteFloat64(val float64) {
|
||||
utils.WriteFloat64ToString(&this.buf, val)
|
||||
}
|
||||
func (this *JsonWriter) WriteString(val string) {
|
||||
valLen := len(val)
|
||||
this.buf = append(this.buf, '"')
|
||||
i := 0
|
||||
for ; i < valLen; i++ {
|
||||
c := val[i]
|
||||
if c > 31 && c != '"' && c != '\\' {
|
||||
this.buf = append(this.buf, c)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == valLen {
|
||||
this.buf = append(this.buf, '"')
|
||||
return
|
||||
}
|
||||
utils.WriteStringSlowPath(&this.buf, i, val, valLen)
|
||||
}
|
||||
func (this *JsonWriter) WriteBytes(val []byte) {
|
||||
this.buf = append(this.buf, val...)
|
||||
}
|
||||
func (this *JsonWriter) Reset() {
|
||||
this.buf = this.buf[:0]
|
||||
this.err = nil
|
||||
this.indention = 0
|
||||
return
|
||||
}
|
||||
func (this *JsonWriter) Buffer() []byte {
|
||||
return this.buf
|
||||
}
|
||||
func (this *JsonWriter) Buffered() int {
|
||||
return len(this.buf)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) Error() error {
|
||||
return this.err
|
||||
}
|
||||
func (this *JsonWriter) SetErr(err error) {
|
||||
this.err = err
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// WriteTrue write true to stream
|
||||
func (stream *JsonWriter) writeTrue() {
|
||||
stream.writeFourBytes('t', 'r', 'u', 'e')
|
||||
}
|
||||
|
||||
// WriteFalse write false to stream
|
||||
func (stream *JsonWriter) writeFalse() {
|
||||
stream.writeFiveBytes('f', 'a', 'l', 's', 'e')
|
||||
}
|
||||
|
||||
func (this *JsonWriter) writeByte(c byte) {
|
||||
this.buf = append(this.buf, c)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) writeTwoBytes(c1 byte, c2 byte) {
|
||||
this.buf = append(this.buf, c1, c2)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3, c4)
|
||||
}
|
||||
|
||||
func (this *JsonWriter) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
|
||||
this.buf = append(this.buf, c1, c2, c3, c4, c5)
|
||||
}
|
||||
|
||||
func (stream *JsonWriter) writeIndention(delta int) {
|
||||
if stream.indention == 0 {
|
||||
return
|
||||
}
|
||||
stream.writeByte('\n')
|
||||
toWrite := stream.indention - delta
|
||||
for i := 0; i < toWrite; i++ {
|
||||
stream.buf = append(stream.buf, ' ')
|
||||
}
|
||||
}
|
31
lego/utils/codec/string.go
Normal file
31
lego/utils/codec/string.go
Normal file
@ -0,0 +1,31 @@
|
||||
package codec
|
||||
|
||||
import "strconv"
|
||||
|
||||
func Atoi(b []byte) (int, error) {
|
||||
return strconv.Atoi(BytesToString(b))
|
||||
}
|
||||
|
||||
func ParseInt(b []byte, base int, bitSize int) (int64, error) {
|
||||
return strconv.ParseInt(BytesToString(b), base, bitSize)
|
||||
}
|
||||
|
||||
func ParseUint(b []byte, base int, bitSize int) (uint64, error) {
|
||||
return strconv.ParseUint(BytesToString(b), base, bitSize)
|
||||
}
|
||||
|
||||
func ParseFloat(b []byte, bitSize int) (float64, error) {
|
||||
return strconv.ParseFloat(BytesToString(b), bitSize)
|
||||
}
|
||||
|
||||
func UintToString(n uint64) string {
|
||||
return BytesToString(strconv.AppendUint([]byte{}, n, 10))
|
||||
}
|
||||
|
||||
func IntToString(n int64) string {
|
||||
return BytesToString(strconv.AppendInt([]byte{}, n, 10))
|
||||
}
|
||||
|
||||
func FloatToString(f float64) string {
|
||||
return BytesToString(strconv.AppendFloat([]byte{}, f, 'f', -1, 64))
|
||||
}
|
136
lego/utils/pools/bufferpool.go
Normal file
136
lego/utils/pools/bufferpool.go
Normal file
@ -0,0 +1,136 @@
|
||||
package pools
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
bytes buffer 缓存池
|
||||
*/
|
||||
|
||||
const _size = 1024
|
||||
|
||||
var bufferPool = &BufferPool{p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Buffer{bs: make([]byte, 0, _size)}
|
||||
},
|
||||
}}
|
||||
|
||||
func BufferPoolGet() *Buffer {
|
||||
return bufferPool.get()
|
||||
}
|
||||
func BufferPoolPut(buf *Buffer) {
|
||||
bufferPool.put(buf)
|
||||
}
|
||||
|
||||
type BufferPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
func (p BufferPool) get() *Buffer {
|
||||
buf := p.p.Get().(*Buffer)
|
||||
buf.reset()
|
||||
buf.pool = p
|
||||
return buf
|
||||
}
|
||||
|
||||
func (p BufferPool) put(buf *Buffer) {
|
||||
p.p.Put(buf)
|
||||
}
|
||||
|
||||
type Buffer struct {
|
||||
bs []byte
|
||||
pool BufferPool
|
||||
}
|
||||
|
||||
func (b *Buffer) reset() {
|
||||
b.bs = b.bs[:0]
|
||||
}
|
||||
func (b *Buffer) Len() int {
|
||||
return len(b.bs)
|
||||
}
|
||||
func (b *Buffer) Cap() int {
|
||||
return cap(b.bs)
|
||||
}
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.bs
|
||||
}
|
||||
func (b *Buffer) String() string {
|
||||
return string(b.bs)
|
||||
}
|
||||
func (b *Buffer) ReadFrom(r io.Reader) (int64, error) {
|
||||
p := b.bs
|
||||
nStart := int64(len(p))
|
||||
nMax := int64(cap(p))
|
||||
n := nStart
|
||||
if nMax == 0 {
|
||||
nMax = 64
|
||||
p = make([]byte, nMax)
|
||||
} else {
|
||||
p = p[:nMax]
|
||||
}
|
||||
for {
|
||||
if n == nMax {
|
||||
nMax *= 2
|
||||
bNew := make([]byte, nMax)
|
||||
copy(bNew, p)
|
||||
p = bNew
|
||||
}
|
||||
nn, err := r.Read(p[n:])
|
||||
n += int64(nn)
|
||||
if err != nil {
|
||||
b.bs = p[:n]
|
||||
n -= nStart
|
||||
if err == io.EOF {
|
||||
return n, nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
}
|
||||
func (b *Buffer) AppendByte(v byte) {
|
||||
b.bs = append(b.bs, v)
|
||||
}
|
||||
func (b *Buffer) AppendInt(i int64) {
|
||||
b.bs = strconv.AppendInt(b.bs, i, 10)
|
||||
}
|
||||
func (b *Buffer) AppendUint(i uint64) {
|
||||
b.bs = strconv.AppendUint(b.bs, i, 10)
|
||||
}
|
||||
func (b *Buffer) AppendFloat(f float64, bitSize int) {
|
||||
b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
|
||||
}
|
||||
func (b *Buffer) AppendBool(v bool) {
|
||||
b.bs = strconv.AppendBool(b.bs, v)
|
||||
}
|
||||
func (b *Buffer) AppendTime(t time.Time, layout string) {
|
||||
b.bs = t.AppendFormat(b.bs, layout)
|
||||
}
|
||||
func (b *Buffer) AppendString(s string) {
|
||||
b.bs = append(b.bs, s...)
|
||||
}
|
||||
func (b *Buffer) AppendBytes(s []byte) {
|
||||
b.bs = append(b.bs, s...)
|
||||
}
|
||||
func (b *Buffer) Write(p []byte) (int, error) {
|
||||
b.bs = append(b.bs, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
func (b *Buffer) WriteString(s string) (int, error) {
|
||||
b.AppendString(s)
|
||||
return len(s), nil
|
||||
}
|
||||
func (b *Buffer) WriteByte(v byte) error {
|
||||
b.AppendByte(v)
|
||||
return nil
|
||||
}
|
||||
func (b *Buffer) WriteTo(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b.bs)
|
||||
return int64(n), err
|
||||
}
|
||||
func (b *Buffer) Free() {
|
||||
b.pool.put(b)
|
||||
}
|
@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"go_dreamfactory/comm"
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/sys/codec"
|
||||
"go_dreamfactory/lego/sys/redis"
|
||||
"go_dreamfactory/lego/utils/codec/json"
|
||||
"go_dreamfactory/modules"
|
||||
"go_dreamfactory/pb"
|
||||
|
||||
@ -101,7 +101,7 @@ func (this *modelChatComp) GetChatQueue(channel pb.ChatChannel, union, group, ar
|
||||
result = make([]*pb.DBChat, len(cdata))
|
||||
for i, v := range cdata {
|
||||
chat := &pb.DBChat{}
|
||||
if err = codec.UnmarshalMapJson(v, chat); err != nil {
|
||||
if err = json.UnmarshalMap(v, chat); err != nil {
|
||||
return
|
||||
}
|
||||
result[i] = chat
|
||||
@ -256,7 +256,7 @@ func (this *modelChatComp) addChatMsg(key string, count int32, msgs ...*pb.DBCha
|
||||
vs = make([]map[string]string, len(msgs))
|
||||
values = make([]interface{}, len(msgs))
|
||||
for i, v := range msgs {
|
||||
if tempdata, err = codec.MarshalMapJson(v); err != nil {
|
||||
if tempdata, err = json.MarshalMap(v); err != nil {
|
||||
this.module.Errorf("err:%v", err)
|
||||
return
|
||||
}
|
||||
|
@ -6,11 +6,12 @@ import (
|
||||
"go_dreamfactory/comm"
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/core/cbase"
|
||||
"go_dreamfactory/lego/sys/codec"
|
||||
ccore "go_dreamfactory/lego/sys/codec/core"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/sys/mgo"
|
||||
"go_dreamfactory/lego/sys/redis"
|
||||
"go_dreamfactory/lego/utils/codec"
|
||||
"go_dreamfactory/lego/utils/codec/codecore"
|
||||
"go_dreamfactory/lego/utils/codec/json"
|
||||
"go_dreamfactory/sys/cache"
|
||||
"go_dreamfactory/sys/db"
|
||||
"reflect"
|
||||
@ -22,6 +23,15 @@ import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var defconf = &codecore.Config{
|
||||
SortMapKeys: true,
|
||||
IndentionStep: 1,
|
||||
OnlyTaggedField: false,
|
||||
DisallowUnknownFields: false,
|
||||
CaseSensitive: false,
|
||||
TagKey: "json",
|
||||
}
|
||||
|
||||
//Redis 自定义脚本 批量读取列表数据
|
||||
var LuaScriptgetList = `
|
||||
local key = tostring(KEYS[1])
|
||||
@ -374,8 +384,8 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
|
||||
sType reflect2.Type
|
||||
sliceType *reflect2.UnsafeSliceType
|
||||
sliceelemType reflect2.Type
|
||||
decoder ccore.IDecoderMapJson
|
||||
encoder ccore.IEncoderMapJson
|
||||
decoder codecore.IDecoderMapJson
|
||||
encoder codecore.IEncoderMapJson
|
||||
dptr unsafe.Pointer
|
||||
elemPtr unsafe.Pointer
|
||||
n int
|
||||
@ -405,7 +415,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
|
||||
err = fmt.Errorf("MCompModel: GetList(sliceelemType non-pointer %T)", data)
|
||||
return
|
||||
}
|
||||
if decoder, ok = codec.DecoderOf(sliceelemType).(ccore.IDecoderMapJson); !ok {
|
||||
if decoder, ok = codec.DecoderOf(sliceelemType, defconf).(codecore.IDecoderMapJson); !ok {
|
||||
err = fmt.Errorf("MCompModel: GetList(data not support MarshalMapJson %T)", data)
|
||||
return
|
||||
}
|
||||
@ -416,13 +426,13 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
|
||||
elemPtr = sliceType.UnsafeGetIndex(dptr, n)
|
||||
if *((*unsafe.Pointer)(elemPtr)) == nil {
|
||||
newPtr := sliceelemType.UnsafeNew()
|
||||
if err = decoder.DecodeForMapJson(newPtr, v); err != nil {
|
||||
if err = decoder.DecodeForMapJson(newPtr, json.GetReader([]byte{}), v); err != nil {
|
||||
log.Errorf("err:%v", err)
|
||||
return
|
||||
}
|
||||
*((*unsafe.Pointer)(elemPtr)) = newPtr
|
||||
} else {
|
||||
decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), v)
|
||||
decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetReader([]byte{}), v)
|
||||
}
|
||||
n++
|
||||
}
|
||||
@ -432,7 +442,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
|
||||
if c, err = this.DB.Find(core.SqlTable(this.TableName), bson.M{"uid": uid}); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if encoder, ok = codec.EncoderOf(sliceelemType).(ccore.IEncoderMapJson); !ok {
|
||||
if encoder, ok = codec.EncoderOf(sliceelemType, defconf).(codecore.IEncoderMapJson); !ok {
|
||||
err = fmt.Errorf("MCompModel: GetList(data not support UnMarshalMapJson %T)", data)
|
||||
return
|
||||
}
|
||||
@ -450,7 +460,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
|
||||
if err = c.Decode(elem); err != nil {
|
||||
return
|
||||
}
|
||||
if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr))); err != nil {
|
||||
if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetWriter()); err != nil {
|
||||
return
|
||||
}
|
||||
key := this.ukeylist(uid, _id)
|
||||
@ -668,33 +678,6 @@ func (this *MCompModel) logOpt(uid string, data interface{}, attrs ...*cache.Ope
|
||||
return nil
|
||||
}
|
||||
|
||||
//获取用户通过扩展表
|
||||
// func (this *MCompModel) GetUserRecord(uid string) (result *pb.DBUserRecord, err error) {
|
||||
// result = &pb.DBUserRecord{}
|
||||
// key := fmt.Sprintf("userrecord:%s{userrecord}", uid)
|
||||
// if err = this.Redis.HGetAll(key, result); err != nil && err != redis.RedisNil {
|
||||
// return
|
||||
// }
|
||||
// if err == redis.RedisNil {
|
||||
// if err = this.DB.FindOne(core.SqlTable("userrecord"), bson.M{"uid": uid}).Decode(result); err != nil {
|
||||
// return
|
||||
// }
|
||||
// err = this.Redis.HMSet(key, result)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
// //修改用户扩展数据
|
||||
// func (this *MCompModel) ChangeUserRecord(uid string, value map[string]interface{}) (err error) {
|
||||
// value["mtime"] = time.Now().Unix() // 更新时间
|
||||
// key := fmt.Sprintf("userrecord:%s{userrecord}", uid)
|
||||
// if err = this.Redis.HMSet(key, value); err != nil && err != redis.RedisNil {
|
||||
// return
|
||||
// }
|
||||
// err = this.UpdateModelLogs("userrecord", uid, bson.M{"uid": uid}, value)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 删除玩家缓存信息
|
||||
func (this *MCompModel) CleanUserRecord(uid string) (err error) {
|
||||
err = this.Redis.Delete(this.ukey(uid))
|
||||
|
@ -1,7 +1,6 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/comm"
|
||||
|
||||
"go_dreamfactory/lego/base"
|
||||
@ -103,33 +102,69 @@ func (this *Gateway) GetMsgDistribute(mtype, stype string) (rule string, ok bool
|
||||
}
|
||||
|
||||
//日志
|
||||
func (this *Gateway) Debugf(format string, a ...interface{}) {
|
||||
if this.options.GetDebug() {
|
||||
this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
//日志接口
|
||||
func (this *Gateway) Debug(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Debug(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Infof(format string, a ...interface{}) {
|
||||
if this.options.GetDebug() {
|
||||
this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
func (this *Gateway) Info(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Info(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Warnf(format string, a ...interface{}) {
|
||||
if this.options.Debug {
|
||||
this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
func (this *Gateway) Print(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Print(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Errorf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
func (this *Gateway) Warn(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Warn(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Panicf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
func (this *Gateway) Error(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Error(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Fatalf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
|
||||
}
|
||||
func (this *Gateway) Panic(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Panic(msg, args...)
|
||||
}
|
||||
func (this *Gateway) Fatal(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Fatal(msg, args...)
|
||||
}
|
||||
|
||||
func (this *Gateway) Debugf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Debugf(format, args...)
|
||||
}
|
||||
func (this *Gateway) Infof(format string, args ...interface{}) {
|
||||
this.options.GetLog().Infof(format, args...)
|
||||
}
|
||||
func (this *Gateway) Printf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Printf(format, args...)
|
||||
}
|
||||
func (this *Gateway) Warnf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Warnf(format, args...)
|
||||
}
|
||||
func (this *Gateway) Errorf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Errorf(format, args...)
|
||||
}
|
||||
func (this *Gateway) Fatalf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Fatalf(format, args...)
|
||||
}
|
||||
func (this *Gateway) Panicf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Panicf(format, args...)
|
||||
}
|
||||
|
||||
func (this *Gateway) Debugln(args ...interface{}) {
|
||||
this.options.GetLog().Debugln(args...)
|
||||
}
|
||||
func (this *Gateway) Infoln(args ...interface{}) {
|
||||
this.options.GetLog().Infoln(args...)
|
||||
}
|
||||
func (this *Gateway) Println(args ...interface{}) {
|
||||
this.options.GetLog().Println(args...)
|
||||
}
|
||||
func (this *Gateway) Warnln(args ...interface{}) {
|
||||
this.options.GetLog().Warnln(args...)
|
||||
}
|
||||
func (this *Gateway) Errorln(args ...interface{}) {
|
||||
this.options.GetLog().Errorln(args...)
|
||||
}
|
||||
func (this *Gateway) Fatalln(args ...interface{}) {
|
||||
this.options.GetLog().Fatalln(args...)
|
||||
}
|
||||
func (this *Gateway) Panicln(args ...interface{}) {
|
||||
this.options.GetLog().Panicln(args...)
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ func (this *ModuleBase) Init(service core.IService, module core.IModule, options
|
||||
this.service = service.(base.IRPCXService)
|
||||
this.module = module
|
||||
this.options = options.(IOptions)
|
||||
this.options.GetLog().SetName("module." + string(module.GetType()))
|
||||
return
|
||||
}
|
||||
|
||||
@ -289,33 +290,68 @@ func (this *ModuleBase) DispenseRes(session comm.IUserSession, res []*cfg.Game_a
|
||||
}
|
||||
|
||||
//日志接口
|
||||
func (this *ModuleBase) Debugf(format string, a ...interface{}) {
|
||||
if this.options.GetDebug() {
|
||||
this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Debug(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Debug(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Infof(format string, a ...interface{}) {
|
||||
if this.options.GetDebug() {
|
||||
this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Info(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Info(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Warnf(format string, a ...interface{}) {
|
||||
if this.options.GetDebug() {
|
||||
this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Print(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Print(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Errorf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Warn(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Warn(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Panicf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Error(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Error(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Fatalf(format string, a ...interface{}) {
|
||||
if this.options.GetLog() != nil {
|
||||
this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
|
||||
}
|
||||
func (this *ModuleBase) Panic(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Panic(msg, args...)
|
||||
}
|
||||
func (this *ModuleBase) Fatal(msg string, args ...log.Field) {
|
||||
this.options.GetLog().Fatal(msg, args...)
|
||||
}
|
||||
|
||||
func (this *ModuleBase) Debugf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Debugf(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Infof(format string, args ...interface{}) {
|
||||
this.options.GetLog().Infof(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Printf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Printf(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Warnf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Warnf(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Errorf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Errorf(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Fatalf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Fatalf(format, args...)
|
||||
}
|
||||
func (this *ModuleBase) Panicf(format string, args ...interface{}) {
|
||||
this.options.GetLog().Panicf(format, args...)
|
||||
}
|
||||
|
||||
func (this *ModuleBase) Debugln(args ...interface{}) {
|
||||
this.options.GetLog().Debugln(args...)
|
||||
}
|
||||
func (this *ModuleBase) Infoln(args ...interface{}) {
|
||||
this.options.GetLog().Infoln(args...)
|
||||
}
|
||||
func (this *ModuleBase) Println(args ...interface{}) {
|
||||
this.options.GetLog().Println(args...)
|
||||
}
|
||||
func (this *ModuleBase) Warnln(args ...interface{}) {
|
||||
this.options.GetLog().Warnln(args...)
|
||||
}
|
||||
func (this *ModuleBase) Errorln(args ...interface{}) {
|
||||
this.options.GetLog().Errorln(args...)
|
||||
}
|
||||
func (this *ModuleBase) Fatalln(args ...interface{}) {
|
||||
this.options.GetLog().Fatalln(args...)
|
||||
}
|
||||
func (this *ModuleBase) Panicln(args ...interface{}) {
|
||||
this.options.GetLog().Panicln(args...)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package modules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"go_dreamfactory/lego/core"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"go_dreamfactory/lego/utils/mapstructure"
|
||||
@ -12,11 +12,11 @@ type (
|
||||
IOptions interface {
|
||||
core.IModuleOptions
|
||||
GetDebug() bool
|
||||
GetLog() log.ILog
|
||||
GetLog() log.ILogger
|
||||
}
|
||||
Options struct {
|
||||
Debug bool //日志是否开启
|
||||
Log log.ILog
|
||||
Log log.ILogger
|
||||
}
|
||||
)
|
||||
|
||||
@ -24,7 +24,7 @@ func (this *Options) GetDebug() bool {
|
||||
return this.Debug
|
||||
}
|
||||
|
||||
func (this *Options) GetLog() log.ILog {
|
||||
func (this *Options) GetLog() log.ILogger {
|
||||
return this.Log
|
||||
}
|
||||
|
||||
@ -32,12 +32,9 @@ func (this *Options) LoadConfig(settings map[string]interface{}) (err error) {
|
||||
if settings != nil {
|
||||
err = mapstructure.Decode(settings, this)
|
||||
}
|
||||
if this.Debug && this.Log == nil {
|
||||
this.Log = log.Clone()
|
||||
if this.Log == nil {
|
||||
err = fmt.Errorf("Log is nil")
|
||||
return
|
||||
}
|
||||
|
||||
if this.Log = log.NewTurnlog(this.Debug, log.Clone("", 2)); this.Log == nil {
|
||||
err = errors.New("log is nil")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -153,11 +153,25 @@ func (this *SCompGateRoute) ReceiveMsg(ctx context.Context, args *pb.AgentMessag
|
||||
data, _ := anypb.New(errdata.(proto.Message))
|
||||
reply.ErrorData = data
|
||||
}
|
||||
log.Errorf("[Handle Api] t:%v m:%s req:%v reply:%v", time.Since(stime), method, msg, reply)
|
||||
// log.Errorf("[Handle Api] t:%v m:%s req:%v reply:%v", time.Since(stime), method, msg, reply)
|
||||
log.Error("[Handle Api]",
|
||||
log.Field{Key: "t", Value: time.Since(stime)},
|
||||
log.Field{Key: "m", Value: method},
|
||||
log.Field{Key: "uid", Value: args.UserId},
|
||||
log.Field{Key: "req", Value: msg},
|
||||
log.Field{Key: "reply", Value: reply},
|
||||
)
|
||||
} else {
|
||||
reply.Reply = session.Polls()
|
||||
if this.options.Debug {
|
||||
log.Debugf("[Handle Api] t:%v m:%s uid:%s req:%v reply:%v", time.Since(stime), method, args.UserId, msg, reply)
|
||||
// log.Debugf("[Handle Api] t:%v m:%s uid:%s req:%v reply:%v", time.Since(stime), method, args.UserId, msg, reply)
|
||||
log.Debug("[Handle Api]",
|
||||
log.Field{Key: "t", Value: time.Since(stime)},
|
||||
log.Field{Key: "m", Value: method},
|
||||
log.Field{Key: "uid", Value: args.UserId},
|
||||
log.Field{Key: "req", Value: msg},
|
||||
log.Field{Key: "reply", Value: reply},
|
||||
)
|
||||
}
|
||||
}
|
||||
} else { //未找到消息处理函数
|
||||
|
37
services/service_test.go
Normal file
37
services/service_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
package services_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_dreamfactory/lego/sys/log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestData struct {
|
||||
Name string
|
||||
Age int32
|
||||
}
|
||||
|
||||
func (this *TestData) Log() {
|
||||
sys.Error("妈妈咪呀!")
|
||||
}
|
||||
|
||||
var sys log.ISys
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
if sys, err = log.NewSys(
|
||||
log.SetFileName("log.log"),
|
||||
log.SetIsDebug(false),
|
||||
log.SetEncoder(log.TextEncoder),
|
||||
); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer os.Exit(m.Run())
|
||||
}
|
||||
func Test_sys(t *testing.T) {
|
||||
data := &TestData{}
|
||||
data.Log()
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user