This commit is contained in:
liwei 2022-08-08 14:06:27 +08:00
commit c6a2bf7dd8
91 changed files with 3159 additions and 5422 deletions

14
go.mod
View File

@ -12,12 +12,9 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/consul/api v1.12.0
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/mitchellh/hashstructure v1.1.0
github.com/modern-go/reflect2 v1.0.2 github.com/modern-go/reflect2 v1.0.2
github.com/nacos-group/nacos-sdk-go v1.0.8 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/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/rs/xid v1.3.0 github.com/rs/xid v1.3.0
@ -31,7 +28,7 @@ require (
github.com/ugorji/go/codec v1.2.7 github.com/ugorji/go/codec v1.2.7
github.com/valyala/fastrand v1.1.0 github.com/valyala/fastrand v1.1.0
go.mongodb.org/mongo-driver v1.5.1 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 golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3
google.golang.org/protobuf v1.28.0 google.golang.org/protobuf v1.28.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
@ -39,11 +36,9 @@ require (
require ( require (
github.com/akutz/memconn v0.1.0 // indirect 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/apache/thrift v0.16.0 // indirect
github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-metrics v0.3.10 // indirect
github.com/aws/aws-sdk-go v1.34.28 // indirect github.com/aws/aws-sdk-go v1.34.28 // indirect
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect
github.com/cenk/backoff v2.2.1+incompatible // indirect github.com/cenk/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cespare/xxhash/v2 v2.1.2 // 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/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
github.com/fatih/color v1.13.0 // indirect github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // 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/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // 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/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/hashicorp/consul/api v1.12.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.2.0 // indirect github.com/hashicorp/go-hclog v1.2.0 // indirect
@ -113,7 +108,6 @@ require (
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
github.com/tinylib/msgp v1.1.6 // indirect github.com/tinylib/msgp v1.1.6 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // 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 v1.6.3 // indirect
go.opentelemetry.io/otel/trace v1.6.3 // indirect go.opentelemetry.io/otel/trace v1.6.3 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // 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/text v0.3.7 // indirect
golang.org/x/tools v0.1.10 // indirect golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
) )

17
go.sum
View File

@ -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/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw= github.com/ChimeraCoder/gojson v1.1.0/go.mod h1:nYbTQlu6hv8PETM15J927yM0zGj3njIldp72UT1MqSw=
@ -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-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk= github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.885 h1:H7Mq9zsKIMvBaw7rEmbWULvSTF2UI/9lFvvm4d/NZdk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.885/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 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 h1:djdFT7f4gF2ttuzRKPbMOWgZajgesItGLwG5FTQKmmE=
github.com/cenk/backoff v2.2.1+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= 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/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-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.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -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/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.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/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/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 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= 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 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 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 v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.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/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 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM=
github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA= github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -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/quick v0.0.0-20220103065406-780def6371e6/go.mod h1:h+J5yoLzf3XMKtM9l4vOaUtS4e+si6T3sKDtheJ15wc=
github.com/smallnest/rpcx v1.7.4 h1:u6ADk/Ep8BqtAoJZO7LbniWsP+nqeAtcbaPm2D4eOXg= github.com/smallnest/rpcx v1.7.4 h1:u6ADk/Ep8BqtAoJZO7LbniWsP+nqeAtcbaPm2D4eOXg=
github.com/smallnest/rpcx v1.7.4/go.mod h1:TSciUoPlm8MYxnC7ErCz5ZymOFxOTbhN9cRgEI6Degs= github.com/smallnest/rpcx v1.7.4/go.mod h1:TSciUoPlm8MYxnC7ErCz5ZymOFxOTbhN9cRgEI6Degs=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 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 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= 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/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 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= 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/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/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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.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/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 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -8,7 +8,6 @@ import (
"go_dreamfactory/lego/base" "go_dreamfactory/lego/base"
"go_dreamfactory/lego/core" "go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase" "go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/event" "go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/rpcx" "go_dreamfactory/lego/sys/rpcx"
@ -85,12 +84,6 @@ func (this *RPCXService) InitSys() {
} else { } else {
log.Infof("Sys event Init success !") 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系统 //初始化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 { 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)) log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err))

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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...)
}
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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, ' ')
}
}

View File

@ -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
}
}

View File

@ -18,13 +18,21 @@ type ISys interface {
var defsys ISys var defsys ISys
func OnInit(config map[string]interface{}, option ...Option) (err error) { func OnInit(config map[string]interface{}, opt ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...)) var option *Options
if option, err = newOptions(config, opt...); err != nil {
return
}
defsys, err = newSys(option)
return return
} }
func NewSys(option ...Option) (sys ISys, err error) { func NewSys(opt ...Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...)) var option *Options
if option, err = newOptionsByOption(opt...); err != nil {
return
}
sys, err = newSys(option)
return return
} }

View File

@ -16,6 +16,7 @@ import (
"go_dreamfactory/lego/sys/gin/binding" "go_dreamfactory/lego/sys/gin/binding"
"go_dreamfactory/lego/sys/gin/render" "go_dreamfactory/lego/sys/gin/render"
"go_dreamfactory/lego/sys/log"
) )
const ( const (
@ -30,17 +31,17 @@ const (
) )
const abortIndex int8 = math.MaxInt8 >> 1 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{ return &Context{
engine: engine, engine: engine,
params: params, params: params,
skippedNodes: skippedNodes, skippedNodes: skippedNodes,
writermem: ResponseWriter{log: sys}, writermem: ResponseWriter{log: log},
} }
} }
type Context struct { type Context struct {
Sys ISys Log log.ILogger
engine *Engine engine *Engine
writermem ResponseWriter writermem ResponseWriter
Request *http.Request Request *http.Request
@ -351,7 +352,7 @@ func (this *Context) initFormCache() {
req := this.Request req := this.Request
if err := req.ParseMultipartForm(this.engine.MaxMultipartMemory); err != nil { if err := req.ParseMultipartForm(this.engine.MaxMultipartMemory); err != nil {
if !errors.Is(err, http.ErrNotMultipart) { 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 this.formCache = req.PostForm

View File

@ -2,8 +2,6 @@ package engine
import ( import (
"net/http" "net/http"
"go_dreamfactory/lego/sys/log"
) )
type HandlerFunc func(*Context) type HandlerFunc func(*Context)
@ -25,11 +23,6 @@ type RouteInfo struct {
type RoutesInfo []RouteInfo type RoutesInfo []RouteInfo
type ISys interface {
log.Ilogf
Debug() bool
}
type IRoutes interface { type IRoutes interface {
Group(relativePath string, handlers ...HandlerFunc) IRoutes Group(relativePath string, handlers ...HandlerFunc) IRoutes
Use(...HandlerFunc) IRoutes Use(...HandlerFunc) IRoutes

View File

@ -9,6 +9,7 @@ import (
"sync" "sync"
"go_dreamfactory/lego/sys/gin/render" "go_dreamfactory/lego/sys/gin/render"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/codec" "go_dreamfactory/lego/utils/codec"
"golang.org/x/net/http2" "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{ engine = &Engine{
RouterGroup: RouterGroup{ RouterGroup: RouterGroup{
Handlers: nil, Handlers: nil,
basePath: "/", basePath: "/",
root: true, root: true,
}, },
sys: sys, log: log,
FuncMap: template.FuncMap{}, FuncMap: template.FuncMap{},
RedirectTrailingSlash: true, RedirectTrailingSlash: true,
RedirectFixedPath: false, RedirectFixedPath: false,
@ -72,7 +73,7 @@ var mimePlain = []string{MIMEPlain}
type Engine struct { type Engine struct {
RouterGroup RouterGroup
sys ISys log log.ILogger
UseRawPath bool UseRawPath bool
/* /*
如果启用路由器尝试修复当前请求路径如果没有 如果启用路由器尝试修复当前请求路径如果没有
@ -194,7 +195,7 @@ func (this *Engine) LoadHTMLGlob(pattern string) {
right := this.delims.Right right := this.delims.Right
templ := template.Must(template.New("").Delims(left, right).Funcs(this.FuncMap).ParseGlob(pattern)) 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.debugPrintLoadTemplate(templ)
this.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: this.FuncMap, Delims: this.delims} this.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: this.FuncMap, Delims: this.delims}
return return
@ -208,7 +209,7 @@ LoadHTMLFiles 加载一段 HTML 文件
并将结果与 HTML 渲染器相关联 并将结果与 HTML 渲染器相关联
*/ */
func (this *Engine) LoadHTMLFiles(files ...string) { 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} this.HTMLRender = render.HTMLDebug{Files: files, FuncMap: this.FuncMap, Delims: this.delims}
return return
} }
@ -218,7 +219,7 @@ func (this *Engine) LoadHTMLFiles(files ...string) {
func (this *Engine) SetHTMLTemplate(templ *template.Template) { func (this *Engine) SetHTMLTemplate(templ *template.Template) {
if len(this.trees) > 0 { 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: at initialization. ie. before any route is registered or the router is listening in a socket:
router := gin.Default() router := gin.Default()
router.SetHTMLTemplate(template) // << good place 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(path[0] == '/', "path must begin with '/'")
assert1(method != "", "HTTP method can not be empty") assert1(method != "", "HTTP method can not be empty")
assert1(len(handlers) > 0, "there must be at least one handler") assert1(len(handlers) > 0, "there must be at least one handler")
if this.sys.Debug() { if this.log.Enabled(log.DebugLevel) {
nuHandlers := len(handlers) nuHandlers := len(handlers)
handlerName := nameOfFunction(handlers.Last()) 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) root := this.trees.get(method)
if root == nil { if root == nil {
@ -406,7 +407,7 @@ func (this *Engine) serveError(c *Context, code int, defaultMessage []byte) {
c.writermem.Header()["Content-Type"] = mimePlain c.writermem.Header()["Content-Type"] = mimePlain
_, err := c.Writer.Write(defaultMessage) _, err := c.Writer.Write(defaultMessage)
if err != nil { 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 return
} }
@ -447,7 +448,7 @@ func (this *Engine) redirectRequest(c *Context) {
if req.Method != http.MethodGet { if req.Method != http.MethodGet {
code = http.StatusTemporaryRedirect 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) http.Redirect(c.Writer, req, rURL, code)
c.writermem.WriteHeaderNow() c.writermem.WriteHeaderNow()
} }
@ -490,22 +491,21 @@ func (this *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) {
func (this *Engine) allocateContext() *Context { func (this *Engine) allocateContext() *Context {
v := make(Params, 0, this.maxParams) v := make(Params, 0, this.maxParams)
skippedNodes := make([]skippedNode, 0, this.maxSections) 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) { func (this *Engine) debugPrintLoadTemplate(tmpl *template.Template) {
if this.sys.Debug() { var buf strings.Builder
var buf strings.Builder for _, tmpl := range tmpl.Templates() {
for _, tmpl := range tmpl.Templates() { buf.WriteString("\t- ")
buf.WriteString("\t- ") buf.WriteString(tmpl.Name())
buf.WriteString(tmpl.Name()) buf.WriteString("\n")
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())
} }
format := "Loaded HTML Templates (%d): \n%s\n"
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
this.log.Debugf(format, len(tmpl.Templates()), buf.String())
} }

View File

@ -33,7 +33,7 @@ type IResponseWriter interface {
} }
type ResponseWriter struct { type ResponseWriter struct {
http.ResponseWriter http.ResponseWriter
log log.Ilogf log log.ILogger
size int size int
status int status int
} }

View File

@ -12,11 +12,11 @@ import (
"go_dreamfactory/lego/sys/gin/middleware/recovery" "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{ sys = &Gin{
options: options, options: options,
} }
sys.engine = engine.NewEngine(sys) sys.engine = engine.NewEngine(options.Log)
///添加基础中间件 ///添加基础中间件
sys.engine.Use(logger.Logger([]string{}), recovery.Recovery()) sys.engine.Use(logger.Logger([]string{}), recovery.Recovery())
if options.CertFile != "" && options.KeyFile != "" { if options.CertFile != "" && options.KeyFile != "" {
@ -28,7 +28,7 @@ func newSys(options Options) (sys *Gin, err error) {
} }
type Gin struct { type Gin struct {
options Options options *Options
server *http.Server server *http.Server
engine *engine.Engine engine *engine.Engine
} }
@ -36,7 +36,7 @@ type Gin struct {
func (this *Gin) Run(listenPort int) (err error) { func (this *Gin) Run(listenPort int) (err error) {
defer func() { defer func() {
if err != nil { if err != nil {
this.Errorf("Run err:%v", err) this.options.Log.Errorf("Run err:%v", err)
} }
}() }()
// if this.engine.IsUnsafeTrustedProxies() { // 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.") // "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{ this.server = &http.Server{
Addr: fmt.Sprintf(":%d", listenPort), Addr: fmt.Sprintf(":%d", listenPort),
Handler: this.engine.Handler(), Handler: this.engine.Handler(),
} }
go func() { go func() {
if err := this.server.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) { 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()) // 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) { 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() { defer func() {
if err != nil { 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() { go func() {
if err := this.server.ListenAndServeTLS(certFile, keyFile); err != nil && errors.Is(err, http.ErrServerClosed) { 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()) // 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) { 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() { defer func() {
if err != nil { 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) { func (this *Gin) Close() (err error) {
if err = this.server.Shutdown(context.Background()); err != nil { if err = this.server.Shutdown(context.Background()); err != nil {
this.Errorf("Close err:%v", err) this.options.Log.Errorln(err)
} }
this.server.Close() this.server.Close()
return 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 { func (this *Gin) StaticFS(relativePath string, fs http.FileSystem) engine.IRoutes {
return this.engine.StaticFS(relativePath, fs) return this.engine.StaticFS(relativePath, fs)
} }
///日志***********************************************************************
func (this *Gin) Debug() bool {
return this.options.Debug
}
func (this *Gin) Debugf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Debugf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Infof(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Infof("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Warnf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Warnf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Errorf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Errorf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Panicf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Panicf("[SYS Gin] "+format, a...)
}
}
func (this *Gin) Fatalf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Fatalf("[SYS Gin] "+format, a...)
}
}

View File

@ -71,7 +71,7 @@ func Logger(SkipPaths []string) engine.HandlerFunc {
path = path + "?" + raw path = path + "?" + raw
} }
param.Path = path 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.TimeStamp.Format("2006/01/02 - 15:04:05"),
param.StatusCode, param.StatusCode,
param.Latency, param.Latency,

View File

@ -73,13 +73,10 @@ func CustomRecoveryWithWriter(handle RecoveryFunc) engine.HandlerFunc {
} }
headersToStr := strings.Join(headers, "\r\n") headersToStr := strings.Join(headers, "\r\n")
if brokenPipe { if brokenPipe {
c.Sys.Errorf("%s\n%s%s", err, headersToStr, reset) c.Log.Errorf("%s\n%s%s", err, headersToStr, reset)
} else if c.Sys.Debug() {
c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s",
timeFormat(time.Now()), headersToStr, err, stack, reset)
} else { } else {
c.Sys.Errorf("[Recovery] %s panic recovered:\n%s\n%s%s", c.Log.Errorf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s",
timeFormat(time.Now()), err, stack, reset) timeFormat(time.Now()), headersToStr, err, stack, reset)
} }
if brokenPipe { if brokenPipe {

View File

@ -1,6 +1,8 @@
package gin package gin
import ( import (
"errors"
"go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure" "go_dreamfactory/lego/utils/mapstructure"
) )
@ -11,7 +13,7 @@ type Options struct {
CertFile string //tls文件 CertFile string //tls文件
KeyFile string //tls文件 KeyFile string //tls文件
Debug bool //日志是否开启 Debug bool //日志是否开启
Log log.ILog Log log.ILogger
} }
func SetListenPort(v int) Option { 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) { return func(o *Options) {
o.Log = v o.Log = v
} }
} }
func newOptions(config map[string]interface{}, opts ...Option) Options { func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) {
options := Options{ options = &Options{
ListenPort: 8080, ListenPort: 8080,
CertFile: "", CertFile: "",
KeyFile: "", KeyFile: "",
Debug: true, Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
} }
if config != nil { if config != nil {
mapstructure.Decode(config, &options) mapstructure.Decode(config, &options)
} }
for _, o := range opts { 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 { func newOptionsByOption(opts ...Option) (options *Options, err error) {
options := Options{ options = &Options{
ListenPort: 8080, ListenPort: 8080,
CertFile: "", CertFile: "",
KeyFile: "", KeyFile: "",
Debug: true, Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
} }
for _, o := range opts { 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
} }

View File

@ -14,7 +14,7 @@ import (
) )
func Test_sys(t *testing.T) { 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) fmt.Printf("log init err:%v", err)
return return
} }

12
lego/sys/log/chown.go Normal file
View File

@ -0,0 +1,12 @@
//go:build !linux
// +build !linux
package log
import (
"os"
)
func chown(_ string, _ os.FileInfo) error {
return nil
}

View 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))
}

View File

@ -1,82 +1,138 @@
package log package log
import ( var AllLevels = []Loglevel{
"fmt" PanicLevel,
"os" FatalLevel,
"strings" ErrorLevel,
WarnLevel,
"go_dreamfactory/lego/utils/flietools" InfoLevel,
) DebugLevel,
}
type ( type (
LogStrut interface {
ToString() (str string)
}
Field struct { Field struct {
Key string Key string
Value interface{} Value interface{}
} }
Ilogf interface { Fields []Field
Debugf(format string, a ...interface{}) Ilogf interface {
Infof(format string, a ...interface{}) Debugf(format string, args ...interface{})
Warnf(format string, a ...interface{}) Infof(format string, args ...interface{})
Errorf(format string, a ...interface{}) Printf(format string, args ...interface{})
Panicf(format string, a ...interface{}) Warnf(format string, args ...interface{})
Fatalf(format string, a ...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 { ILog interface {
Clone(option ...Option) ILog Debug(msg string, args ...Field)
Debug(msg string, fields ...Field) Info(msg string, args ...Field)
Info(msg string, fields ...Field) Print(msg string, args ...Field)
Warn(msg string, fields ...Field) Warn(msg string, args ...Field)
Error(msg string, fields ...Field) Error(msg string, args ...Field)
Panic(msg string, fields ...Field) Fatal(msg string, args ...Field)
Fatal(msg string, fields ...Field) Panic(msg string, args ...Field)
}
ILogger interface {
SetName(name string)
Enabled(lvl Loglevel) bool
Ilogf Ilogf
IlogIn
ILog
}
ISys interface {
Clone(name string, skip int) ILogger
ILogger
} }
) )
var ( var (
defsys ILog defsys ISys
) )
func OnInit(config map[string]interface{}, option ...Option) (err error) { func OnInit(config map[string]interface{}, opt ...Option) (err error) {
defsys, err = newSys(newOptions(config, option...)) var option *Options
return if option, err = newOptions(config, opt...); err != nil {
} return
func NewSys(option ...Option) (sys ILog, err error) { }
sys, err = newSys(newOptionsByOption(option...)) defsys, err = newSys(option)
return return
} }
func Clone(option ...Option) ILog { func NewSys(opt ...Option) (sys ISys, err error) {
if defsys != nil { var option *Options
return defsys.Clone(option...) if option, err = newOptionsByOption(opt...); err != nil {
return
} }
return nil sys, err = newSys(option)
return
} }
func Clone(name string, skip int) ILogger {
func Debug(msg string, fields ...Field) { defsys.Debug(msg, fields...) } return defsys.Clone(name, skip)
func Info(msg string, fields ...Field) { defsys.Info(msg, fields...) } }
func Warn(msg string, fields ...Field) { defsys.Warn(msg, fields...) } func Debug(msg string, args ...Field) {
func Error(msg string, fields ...Field) { defsys.Error(msg, fields...) } defsys.Debug(msg, args...)
func Panic(msg string, fields ...Field) { defsys.Panic(msg, fields...) } }
func Fatal(msg string, fields ...Field) { defsys.Fatal(msg, fields...) } func Info(msg string, args ...Field) {
func Debugf(format string, a ...interface{}) { defsys.Debugf(format, a...) } defsys.Info(msg, args...)
func Infof(format string, a ...interface{}) { defsys.Infof(format, a...) } }
func Warnf(format string, a ...interface{}) { defsys.Warnf(format, a...) } func Warn(msg string, args ...Field) {
func Errorf(format string, a ...interface{}) { defsys.Errorf(format, a...) } defsys.Warn(msg, args...)
func Panicf(format string, a ...interface{}) { defsys.Panicf(format, a...) } }
func Fatalf(format string, a ...interface{}) { defsys.Fatalf(format, a...) } func Error(msg string, args ...Field) {
defsys.Error(msg, args...)
//创建日志文件 }
func createlogfile(logpath string) error { func Fatal(msg string, args ...Field) {
logdir := string(logpath[0:strings.LastIndex(logpath, "/")]) defsys.Fatal(msg, args...)
if !flietools.IsExist(logdir) { }
err := os.MkdirAll(logdir, os.ModePerm) func Panic(msg string, args ...Field) {
if err != nil { defsys.Panic(msg, args...)
return fmt.Errorf("创建日志路径失败 1" + err.Error()) }
} func Debugf(format string, args ...interface{}) {
} defsys.Debugf(format, args...)
return nil }
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
View 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
View 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
View 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)
}

View 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
View 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
View 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]
}

View File

@ -1,114 +1,139 @@
package log package log
import ( import (
"errors"
"go_dreamfactory/lego/utils/mapstructure" "go_dreamfactory/lego/utils/mapstructure"
) )
type Loglevel int8
const (
DebugLevel Loglevel = iota
InfoLevel
WarnLevel
ErrorLevel
PanicLevel
FatalLevel
)
type LogEncoder int8 type LogEncoder int8
const ( const (
Console LogEncoder = iota TextEncoder LogEncoder = iota
JSON JSONEncoder
) )
type Option func(*Options) type Option func(*Options)
type Options struct { type Options struct {
FileName string //日志文件名包含 FileName string //日志文件名包含
Loglevel Loglevel //日志输出级别 Loglevel Loglevel //日志输出级别
Debugmode bool //是否debug模式 IsDebug bool //是否是开发模式
Encoder LogEncoder //日志输出样式 ReportCaller bool //是否输出堆栈信息
Loglayer int //日志堆栈信息打印层级 CallerSkip int //堆栈深度
LogMaxSize int //每个日志文件最大尺寸 单位 M 默认 1024M Encoder LogEncoder //日志输出样式
LogMaxBackups int //最多保留备份个数 默认 10个 CupTimeTime int //日志分割时间 单位 小时
LogMaxAge int //文件最多保存多少天 默认 7天 MaxAgeTime int //日志最大保存时间 单位天
MaxBackups int //最大备份日志个数
Compress bool //是否压缩备份日志
} }
///日志文件名包含
func SetFileName(v string) Option { func SetFileName(v string) Option {
return func(o *Options) { return func(o *Options) {
o.FileName = v 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 { func SetLoglevel(v Loglevel) Option {
return func(o *Options) { return func(o *Options) {
o.Loglevel = v o.Loglevel = v
} }
} }
func SetDebugMode(v bool) Option { func SetReportCaller(v bool) Option {
return func(o *Options) { 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 { func SetEncoder(v LogEncoder) Option {
return func(o *Options) { return func(o *Options) {
o.Encoder = v o.Encoder = v
} }
} }
func SetLoglayer(v int) Option {
///日志分割时间 单位 小时
func SetRotationTime(v int) Option {
return func(o *Options) { return func(o *Options) {
o.Loglayer = v o.CupTimeTime = v
}
}
func SetLogMaxSize(v int) Option {
return func(o *Options) {
o.LogMaxSize = v
}
}
func SetLogMaxBackups(v int) Option {
return func(o *Options) {
o.LogMaxBackups = v
}
}
func SetLogMaxAge(v int) Option {
return func(o *Options) {
o.LogMaxAge = v
} }
} }
func newOptions(config map[string]interface{}, opts ...Option) Options { ///日志最大保存时间 单位天
options := Options{ func SetMaxAgeTime(v int) Option {
FileName: "./lego.log", return func(o *Options) {
Loglevel: WarnLevel, o.MaxAgeTime = v
Debugmode: false, }
Encoder: Console, }
Loglayer: 2,
LogMaxSize: 1024, ///日志备份最大文件数
LogMaxBackups: 10, func SetMaxBackups(v int) Option {
LogMaxAge: 7, 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 { if config != nil {
mapstructure.Decode(config, &options) mapstructure.Decode(config, options)
} }
for _, o := range opts { 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 { func newOptionsByOption(opts ...Option) (options *Options, err error) {
options := Options{ options = &Options{
FileName: "./lego.log", FileName: "log.log",
Loglevel: WarnLevel, Loglevel: DebugLevel,
Debugmode: false, CupTimeTime: 24,
Loglayer: 2, MaxAgeTime: 7,
LogMaxSize: 1024, MaxBackups: 250,
LogMaxBackups: 10, Compress: false,
LogMaxAge: 7, Encoder: TextEncoder,
CallerSkip: 0,
ReportCaller: false,
IsDebug: true,
} }
for _, o := range opts { for _, o := range opts {
o(&options) o(options)
} }
return options return
} }

156
lego/sys/log/stacktrace.go Normal file
View 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))
}

View File

@ -13,14 +13,18 @@ type TestData struct {
Age int32 Age int32
} }
var sys log.ILog func (this *TestData) Log() {
sys.Error("妈妈咪呀!")
}
var sys log.ISys
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
var err error var err error
if sys, err = log.NewSys( if sys, err = log.NewSys(
log.SetFileName("./log.log"), log.SetFileName("log.log"),
log.SetDebugMode(false), log.SetIsDebug(false),
log.SetLoglayer(2), log.SetEncoder(log.TextEncoder),
); err != nil { ); err != nil {
fmt.Println(err) fmt.Println(err)
return return
@ -28,10 +32,12 @@ func TestMain(m *testing.M) {
defer os.Exit(m.Run()) defer os.Exit(m.Run())
} }
func Test_sys(t *testing.T) { 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 for i := 0; i < b.N; i++ { //use b.N for looping
sys.Error("妈妈咪呀!") sys.Error("妈妈咪呀!")
} }

132
lego/sys/log/turnlog.go Normal file
View 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...)
}
}

View 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
}

View File

@ -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...)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -5,9 +5,9 @@ import (
"fmt" "fmt"
"time" "time"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/redis/cluster" "go_dreamfactory/lego/sys/redis/cluster"
"go_dreamfactory/lego/sys/redis/single" "go_dreamfactory/lego/sys/redis/single"
"go_dreamfactory/lego/utils/codec/json"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
) )
@ -378,41 +378,41 @@ func (this *Redis) Marshal(v interface{}) ([]byte, error) {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.Marshal(v) return this.options.Codec.Marshal(v)
} else { } else {
return codec.MarshalJson(v) return json.Marshal(v)
} }
} }
func (this *Redis) Unmarshal(data []byte, v interface{}) error { func (this *Redis) Unmarshal(data []byte, v interface{}) error {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.Unmarshal(data, v) return this.options.Codec.Unmarshal(data, v)
} else { } else {
return codec.UnmarshalJson(data, v) return json.Unmarshal(data, v)
} }
} }
func (this *Redis) MarshalMap(val interface{}) (ret map[string]string, err error) { func (this *Redis) MarshalMap(val interface{}) (ret map[string]string, err error) {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.MarshalMap(val) return this.options.Codec.MarshalMap(val)
} else { } else {
return codec.MarshalMapJson(val) return json.MarshalMap(val)
} }
} }
func (this *Redis) UnmarshalMap(data map[string]string, val interface{}) (err error) { func (this *Redis) UnmarshalMap(data map[string]string, val interface{}) (err error) {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.UnmarshalMap(data, val) return this.options.Codec.UnmarshalMap(data, val)
} else { } else {
return codec.UnmarshalMapJson(data, val) return json.UnmarshalMap(data, val)
} }
} }
func (this *Redis) MarshalSlice(val interface{}) (ret []string, err error) { func (this *Redis) MarshalSlice(val interface{}) (ret []string, err error) {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.MarshalSlice(val) return this.options.Codec.MarshalSlice(val)
} else { } else {
return codec.MarshalSliceJson(val) return json.MarshalSlice(val)
} }
} }
func (this *Redis) UnmarshalSlice(data []string, val interface{}) (err error) { func (this *Redis) UnmarshalSlice(data []string, val interface{}) (err error) {
if this.options.Codec != nil { if this.options.Codec != nil {
return this.options.Codec.UnmarshalSlice(data, val) return this.options.Codec.UnmarshalSlice(data, val)
} else { } else {
return codec.UnmarshalSliceJson(data, val) return json.UnmarshalSlice(data, val)
} }
} }

View File

@ -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
}

View File

@ -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) {
}

View File

@ -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,
})
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}
}
}

View File

@ -1,10 +0,0 @@
package registry
func newZookeeper(options Options) (sys *Zookeeper_Registry, err error) {
return
}
type Zookeeper_Registry struct {
options Options
}

View File

@ -36,6 +36,7 @@ type Client struct {
metadata string metadata string
writeTimeout time.Duration writeTimeout time.Duration
AsyncWrite bool AsyncWrite bool
clusterMu sync.RWMutex
clusterClients map[string]map[string]client.XClient //其他集群客户端 clusterClients map[string]map[string]client.XClient //其他集群客户端
connsMapMu sync.RWMutex connsMapMu sync.RWMutex
conns map[string]net.Conn conns map[string]net.Conn
@ -51,15 +52,15 @@ func (this *Client) DoMessage() {
for msg := range this.msgChan { for msg := range this.msgChan {
go func(req *protocol.Message) { go func(req *protocol.Message) {
if req.ServicePath != "" && req.ServiceMethod != "" { if req.ServicePath != "" && req.ServiceMethod != "" {
this.Debugf("DoMessage :%v", req) this.options.Log.Debugf("DoMessage :%v", req)
addr, ok := req.Metadata[ServiceAddrKey] addr, ok := req.Metadata[ServiceAddrKey]
if !ok { if !ok {
this.Errorf("Metadata no found ServiceAddrKey!") this.options.Log.Errorf("Metadata no found ServiceAddrKey!")
return return
} }
conn, ok := this.conns[addr] conn, ok := this.conns[addr]
if !ok { if !ok {
this.Errorf("no found conn addr:%s", addr) this.options.Log.Errorf("no found conn addr:%s", addr)
return return
} }
res, _ := this.handleRequest(context.Background(), req) res, _ := this.handleRequest(context.Background(), req)
@ -86,6 +87,19 @@ func (this *Client) Stop() (err error) {
return 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 服务 //注册Rpc 服务
func (this *Client) RegisterFunction(fn interface{}) (err error) { func (this *Client) RegisterFunction(fn interface{}) (err error) {
_, err = this.registerFunction(this.options.ServiceType, fn, "", false) _, err = this.registerFunction(this.options.ServiceType, fn, "", false)
@ -247,12 +261,12 @@ func (this *Client) UpdateServer(servers map[string]*ServiceNode) {
ServiceType: this.options.ServiceType, ServiceType: this.options.ServiceType,
ServiceAddr: this.options.ServiceAddr}, ServiceAddr: this.options.ServiceAddr},
&ServiceNode{}); err != nil { &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() this.connectMapMu.Lock()
delete(this.connecting, v.ServiceAddr) delete(this.connecting, v.ServiceAddr)
this.connectMapMu.Unlock() this.connectMapMu.Unlock()
} else { } 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.connsMapMu.Lock()
this.conns[addr] = conn this.conns[addr] = conn
this.connsMapMu.Unlock() this.connsMapMu.Unlock()
this.Debugf("ClientConnected addr:%v", addr) this.options.Log.Debugf("ClientConnected addr:%v", addr)
return conn, nil return conn, nil
} }
@ -275,51 +289,10 @@ func (this *Client) ClientConnectionClose(conn net.Conn) error {
this.connsMapMu.Lock() this.connsMapMu.Lock()
delete(this.conns, addr) delete(this.conns, addr)
this.connsMapMu.Unlock() this.connsMapMu.Unlock()
this.Debugf("ClientConnectionClose addr:%v", addr) this.options.Log.Debugf("ClientConnectionClose addr:%v", addr)
return nil 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) { func (this *Client) getclient(ctx *context.Context, clusterTag string, servicePath string) (c client.XClient, err error) {
if servicePath == "" { if servicePath == "" {
@ -392,7 +365,7 @@ func (this *Client) registerFunction(servicePath string, fn interface{}, name st
} }
if fname == "" { if fname == "" {
errorStr := "rpcx.registerFunction: no func name for type " + f.Type().String() errorStr := "rpcx.registerFunction: no func name for type " + f.Type().String()
this.Errorf(errorStr) this.options.Log.Errorf(errorStr)
return fname, errors.New(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 { } else if replyv != nil {
reflectTypePools.Put(mtype.ReplyType, replyv) 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 return res, nil
} }

View File

@ -22,6 +22,7 @@ type (
ISys interface { ISys interface {
Start() (err error) Start() (err error)
Stop() (err error) Stop() (err error)
GetServiceTags() []string
RegisterFunction(fn interface{}) (err error) RegisterFunction(fn interface{}) (err error)
RegisterFunctionName(name string, fn interface{}) (err error) RegisterFunctionName(name string, fn interface{}) (err error)
UnregisterAll() (err error) UnregisterAll() (err error)

View File

@ -28,7 +28,7 @@ type Options struct {
AutoConnect bool //自动连接 客户端启动模式下 主动连接发现的节点服务器 AutoConnect bool //自动连接 客户端启动模式下 主动连接发现的节点服务器
SerializeType protocol.SerializeType SerializeType protocol.SerializeType
Debug bool //日志是否开启 Debug bool //日志是否开启
Log log.ILog Log log.ILogger
} }
func SetServiceTag(v string) Option { func SetServiceTag(v string) Option {
@ -79,7 +79,7 @@ func SetDebug(v bool) Option {
o.Debug = v o.Debug = v
} }
} }
func SetLog(v log.ILog) Option { func SetLog(v log.ILogger) Option {
return func(o *Options) { return func(o *Options) {
o.Log = v 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: 启动参数异常") return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常")
} }
if options.Debug && options.Log == nil { 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") err = errors.New("log is nil")
} }
} }
@ -111,8 +111,6 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) {
options = &Options{ options = &Options{
AutoConnect: true, AutoConnect: true,
SerializeType: protocol.MsgPack, SerializeType: protocol.MsgPack,
Debug: true,
Log: log.Clone(log.SetLoglayer(2)),
} }
for _, o := range opts { for _, o := range opts {
o(options) o(options)
@ -121,7 +119,7 @@ func newOptionsByOption(opts ...Option) (options *Options, err error) {
return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常") return options, errors.New("[Sys.RPCX] newOptions err: 启动参数异常")
} }
if options.Debug && options.Log == nil { 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") err = errors.New("log is nil")
} }
} }

View File

@ -46,6 +46,10 @@ func (this *RPCX) Stop() (err error) {
return return
} }
//获取服务集群列表
func (this *RPCX) GetServiceTags() []string {
return this.GetServiceTags()
}
func (this *RPCX) RegisterFunction(fn interface{}) (err error) { func (this *RPCX) RegisterFunction(fn interface{}) (err error) {
this.service.RegisterFunction(fn) this.service.RegisterFunction(fn)
return return

View File

@ -63,7 +63,7 @@ type Service struct {
func (this *Service) Start() (err error) { func (this *Service) Start() (err error) {
go func() { go func() {
if err = this.server.Serve("tcp", this.options.ServiceAddr); err != nil { 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 return
@ -75,6 +75,19 @@ func (this *Service) Stop() (err error) {
return 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 服务 //注册RPC 服务
func (this *Service) RegisterFunction(fn interface{}) (err error) { func (this *Service) RegisterFunction(fn interface{}) (err error) {
err = this.server.RegisterFunction(this.options.ServiceType, fn, this.metadata) 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 ok bool
) )
req_metadata := r.Metadata 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 { if stag, ok = req_metadata[ServiceClusterTag]; ok {
this.selectormutex.RLock() this.selectormutex.RLock()
selector, ok = this.selectors[stag] selector, ok = this.selectors[stag]
@ -228,7 +241,7 @@ func (this *Service) PostReadRequest(ctx context.Context, r *protocol.Message, e
} }
this.clientmutex.Unlock() this.clientmutex.Unlock()
selector.UpdateServer(servers) 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() this.mutex.Unlock()
switch { switch {
case call == nil: 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: case r.MessageStatusType() == protocol.Error:
if len(r.Metadata) > 0 { if len(r.Metadata) > 0 {
call.ResMetadata = r.Metadata call.ResMetadata = r.Metadata
@ -284,42 +297,6 @@ func (this *Service) RpcxShakeHands(ctx context.Context, args *ServiceNode, repl
return nil 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) { 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 ( var (

View File

@ -3,29 +3,11 @@ package codec
import ( import (
"encoding/binary" "encoding/binary"
"math" "math"
"strconv"
"unsafe" "unsafe"
) )
const host32bit = ^uint(0)>>32 == 0 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 // string
func BytesToString(b []byte) string { func BytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b)) return *(*string)(unsafe.Pointer(&b))
@ -186,31 +168,3 @@ func BytesToBool(buf []byte) bool {
var data bool = buf[0] != 0 var data bool = buf[0] != 0
return data 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
View 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
}

View File

@ -1,65 +1,43 @@
package codec package codec_test
import ( import (
"encoding/json"
"fmt" "fmt"
"go_dreamfactory/lego/utils/codec/json"
"testing" "testing"
) )
type TestData struct { type TestData struct {
Fild_1 string Name string
Fild_3 int Value int
Fild_4 float32 Array []interface{}
Data map[string]interface{}
}
type Test1Data struct {
Name string
Value int
} }
func Test_Encoder(t *testing.T) { func Test_sys_slice(t *testing.T) {
encoder := &Encoder{} data := []*Test1Data{{"liwe", 1}, {"liwe2", 2}}
// data, err := encoder.EncoderToMap(map[string]interface{}{"liwei": 106, "sasd": "2564"}) d, err := json.Marshal(data)
// fmt.Printf("EncoderToMap data1:%v err:%v", data, err) fmt.Printf("codec Marshal d:%s err:%v", d, err)
data, err := encoder.EncoderToMap([]interface{}{"liwei", 106, "sasd", "2564"}) data = []*Test1Data{}
fmt.Printf("EncoderToMap data1:%v err:%v", data, err) err = json.Unmarshal(d, &data)
// data, err := encoder.EncoderToMap(&TestData{Fild_1: "liwei1dao", Fild_3: 25, Fild_4: 3.54}) fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
// fmt.Printf("EncoderToMap data2:%v err:%v", data, err)
} }
func Test_sys_json(t *testing.T) {
func Test_Decoder(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}})
decoder := &Decoder{} fmt.Printf("codec Marshal d:%s err:%v", d, err)
data := &TestData{} data := &TestData{}
err := decoder.DecoderMapString(map[string]string{"Fild_1": "liwei1dao"}, data) err = json.Unmarshal(d, data)
fmt.Printf("DecoderMap data1:%v err:%v", data, err) fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
} }
func Test_Slice_Decoder(t *testing.T) { func Test_sys_mapjson(t *testing.T) {
decoder := &Decoder{DefDecoder: json.Unmarshal} 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}})
encoder := &Encoder{DefEncoder: json.Marshal} fmt.Printf("codec Marshal d:%s err:%v", d, err)
data := []*TestData{{Fild_1: "1dao", Fild_3: 10, Fild_4: 3.5}, {Fild_1: "2dao", Fild_3: 20, Fild_4: 6.5}} data := &TestData{}
datastr, err := encoder.EncoderToSliceString(data) err = json.UnmarshalMap(d, data)
fmt.Printf("EncoderToSliceString datastr:%v err:%v", datastr, err) fmt.Printf("codec UnmarshalJson data:%v err:%v", data, 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_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)
} }

View File

@ -1,4 +1,4 @@
package core package codecore
import ( import (
"reflect" "reflect"
@ -7,15 +7,6 @@ import (
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
) )
//数据类型
type CodecType int8
const (
Json CodecType = iota //json 格式数据
Bytes //byte 字节流数据
Proto //proto google protobuff 数据
)
//结构值类型 //结构值类型
type ValueType int type ValueType int
@ -37,18 +28,14 @@ const (
) )
type ( type (
ICodec interface { IPools interface {
Options() *Options GetReader(buf []byte) IReader
GetEncoderFromCache(cacheKey uintptr) IEncoder PutReader(w IReader)
GetDecoderFromCache(cacheKey uintptr) IDecoder GetWriter() IWriter
EncoderOf(typ reflect2.Type) IEncoder PutWriter(w IWriter)
DecoderOf(typ reflect2.Type) IDecoder
BorrowExtractor(buf []byte) IExtractor //借 提取器
ReturnExtractor(extra IExtractor) //还 提取器
BorrowStream() IStream //借 输出对象
ReturnStream(stream IStream) //换 输出对象
} }
IExtractor interface { IReader interface {
IPools
ReadVal(obj interface{}) //读取指定类型对象 ReadVal(obj interface{}) //读取指定类型对象
WhatIsNext() ValueType WhatIsNext() ValueType
Read() interface{} Read() interface{}
@ -80,7 +67,8 @@ type (
Error() error Error() error
SetErr(err error) SetErr(err error)
} }
IStream interface { IWriter interface {
IPools
WriteVal(val interface{}) //写入一个对象 WriteVal(val interface{}) //写入一个对象
WriteNil() //写空 null WriteNil() //写空 null
WriteEmptyArray() //写空数组 [] WriteEmptyArray() //写空数组 []
@ -107,42 +95,36 @@ type (
WriteFloat64(val float64) WriteFloat64(val float64)
WriteString(val string) WriteString(val string)
WriteBytes(val []byte) WriteBytes(val []byte)
Reset(bufSize int) Reset()
Buffer() []byte //返回缓存区数据 Buffer() []byte //返回缓存区数据
Buffered() int
Error() error Error() error
SetErr(err 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 { IDecoder interface {
GetType() reflect.Kind GetType() reflect.Kind
Decode(ptr unsafe.Pointer, extra IExtractor) Decode(ptr unsafe.Pointer, r IReader)
} }
//MapJson 解码器 //MapJson 解码器
IDecoderMapJson interface { 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 解码器 //MapJson 解码器
IDecoderSliceJson interface { IDecoderSliceJson interface {
DecodeForSliceJson(ptr unsafe.Pointer, extra []string) (err error) DecodeForSliceJson(ptr unsafe.Pointer, r IReader, extra []string) (err error)
} }
//空校验 IEncoder interface {
CheckIsEmpty interface { GetType() reflect.Kind
IsEmpty(ptr unsafe.Pointer) bool 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 { 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 { type Ctx struct {
ICodec Config *Config
Prefix string Prefix string
Encoders map[reflect2.Type]IEncoder Encoders map[reflect2.Type]IEncoder
Decoders map[reflect2.Type]IDecoder Decoders map[reflect2.Type]IDecoder
@ -159,7 +150,7 @@ type Ctx struct {
func (this *Ctx) Append(prefix string) *Ctx { func (this *Ctx) Append(prefix string) *Ctx {
return &Ctx{ return &Ctx{
ICodec: this.ICodec, Config: this.Config,
Prefix: this.Prefix + " " + prefix, Prefix: this.Prefix + " " + prefix,
Encoders: this.Encoders, Encoders: this.Encoders,
Decoders: this.Decoders, Decoders: this.Decoders,

View 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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "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] encoder := ctx.Encoders[typ]
if encoder != nil { if encoder != nil {
return encoder return encoder
@ -47,8 +47,8 @@ func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
return encoder return encoder
} }
func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder { func _createEncoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IEncoder {
var encoder core.IEncoder var encoder codecore.IEncoder
encoder = createEncoderOfNative(ctx, typ) encoder = createEncoderOfNative(ctx, typ)
if encoder != nil { if encoder != nil {
return encoder 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] decoder := ctx.Decoders[typ]
if decoder != nil { if decoder != nil {
return decoder return decoder
@ -84,8 +84,8 @@ func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
return decoder return decoder
} }
func _createDecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder { func _createDecoderOfType(ctx *codecore.Ctx, typ reflect2.Type) codecore.IDecoder {
var decoder core.IDecoder var decoder codecore.IDecoder
decoder = createDecoderOfNative(ctx, typ) decoder = createDecoderOfNative(ctx, typ)
if decoder != nil { if decoder != nil {
@ -129,25 +129,25 @@ func StringToBytes(s string) []byte {
//根节点 ------------------------------------------------------------------- //根节点 -------------------------------------------------------------------
type rootDecoder struct { type rootDecoder struct {
decoder core.IDecoder decoder codecore.IDecoder
} }
func (this *rootDecoder) GetType() reflect.Kind { func (this *rootDecoder) GetType() reflect.Kind {
return reflect.Ptr return reflect.Ptr
} }
func (this *rootDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { func (this *rootDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) {
this.decoder.Decode(ptr, extra) this.decoder.Decode(ptr, r)
} }
type rootEncoder struct { type rootEncoder struct {
encoder core.IEncoder encoder codecore.IEncoder
} }
func (this *rootEncoder) GetType() reflect.Kind { func (this *rootEncoder) GetType() reflect.Kind {
return reflect.Ptr return reflect.Ptr
} }
func (this *rootEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { func (this *rootEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
this.encoder.Encode(ptr, stream) this.encoder.Encode(ptr, w)
} }
func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool { func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool {
@ -155,12 +155,12 @@ func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
//onePtrEncoder--------------------------------------------------------------- //onePtrEncoder---------------------------------------------------------------
func NewonePtrEncoder(encoder core.IEncoder) core.IEncoder { func NewonePtrEncoder(encoder codecore.IEncoder) codecore.IEncoder {
return &onePtrEncoder{encoder} return &onePtrEncoder{encoder}
} }
type onePtrEncoder struct { type onePtrEncoder struct {
encoder core.IEncoder encoder codecore.IEncoder
} }
func (this *onePtrEncoder) GetType() reflect.Kind { 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)) 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) this.encoder.Encode(unsafe.Pointer(&ptr), stream)
} }
func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
if encoderMapJson, ok := this.encoder.(core.IEncoderMapJson); !ok { if encoderMapJson, ok := this.encoder.(codecore.IEncoderMapJson); !ok {
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.encoder) err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.encoder)
return return
} else { } 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 { func (this *lazyErrorDecoder) GetType() reflect.Kind {
return reflect.Ptr 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 { if extra.Error() == nil {
extra.SetErr(this.err) extra.SetErr(this.err)
} }
@ -206,7 +206,7 @@ func (this *lazyErrorEncoder) GetType() reflect.Kind {
return reflect.Ptr 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 { if ptr == nil {
stream.WriteNil() stream.WriteNil()
} else if stream.Error() == nil { } else if stream.Error() == nil {

View File

@ -7,37 +7,36 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "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) arrayType := typ.(*reflect2.UnsafeArrayType)
decoder := DecoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem()) 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) arrayType := typ.(*reflect2.UnsafeArrayType)
if arrayType.Len() == 0 { if arrayType.Len() == 0 {
return &emptyArrayEncoder{} return &emptyArrayEncoder{}
} }
encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem()) encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
return &arrayEncoder{ctx.ICodec, arrayType, encoder} return &arrayEncoder{arrayType, encoder}
} }
//array------------------------------------------------------------------------------------------------------------------------------- //array-------------------------------------------------------------------------------------------------------------------------------
type arrayEncoder struct { type arrayEncoder struct {
codec core.ICodec
arrayType *reflect2.UnsafeArrayType arrayType *reflect2.UnsafeArrayType
elemEncoder core.IEncoder elemEncoder codecore.IEncoder
} }
func (codec *arrayEncoder) GetType() reflect.Kind { func (codec *arrayEncoder) GetType() reflect.Kind {
return reflect.Array 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() stream.WriteArrayStart()
elemPtr := unsafe.Pointer(ptr) elemPtr := unsafe.Pointer(ptr)
this.elemEncoder.Encode(elemPtr, stream) this.elemEncoder.Encode(elemPtr, stream)
@ -57,32 +56,30 @@ func (this *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
//编码对象到json数组 //编码对象到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()) ret = make([]string, this.arrayType.Len())
stream := this.codec.BorrowStream()
for i := 1; i < this.arrayType.Len(); i++ { for i := 1; i < this.arrayType.Len(); i++ {
elemPtr := this.arrayType.UnsafeGetIndex(ptr, i) elemPtr := this.arrayType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream) this.elemEncoder.Encode(elemPtr, w)
if stream.Error() != nil && stream.Error() != io.EOF { if w.Error() != nil && w.Error() != io.EOF {
err = stream.Error() err = w.Error()
return return
} }
ret[i] = BytesToString(stream.Buffer()) ret[i] = BytesToString(w.Buffer())
stream.Reset(512) w.Reset()
} }
return return
} }
type arrayDecoder struct { type arrayDecoder struct {
codec core.ICodec
arrayType *reflect2.UnsafeArrayType arrayType *reflect2.UnsafeArrayType
elemDecoder core.IDecoder elemDecoder codecore.IDecoder
} }
func (codec *arrayDecoder) GetType() reflect.Kind { func (codec *arrayDecoder) GetType() reflect.Kind {
return reflect.Array 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 arrayType := this.arrayType
if extra.ReadNil() { if extra.ReadNil() {
return 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 arrayType := this.arrayType
if data == nil { if data == nil {
err = errors.New("extra is nil") err = errors.New("extra is nil")
return return
} }
extra := this.codec.BorrowExtractor([]byte{})
arrayType.UnsafeGetIndex(ptr, len(data)) arrayType.UnsafeGetIndex(ptr, len(data))
for i, v := range data { for i, v := range data {
elemPtr := arrayType.UnsafeGetIndex(ptr, i) elemPtr := arrayType.UnsafeGetIndex(ptr, i)
extra.ResetBytes(StringToBytes(v)) r.ResetBytes(StringToBytes(v))
this.elemDecoder.Decode(elemPtr, extra) this.elemDecoder.Decode(elemPtr, r)
if extra.Error() != nil && extra.Error() != io.EOF { if r.Error() != nil && r.Error() != io.EOF {
err = extra.Error() err = r.Error()
return return
} }
} }
@ -136,7 +132,7 @@ func (this *emptyArrayEncoder) GetType() reflect.Kind {
return reflect.Array 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() stream.WriteEmptyArray()
} }

View File

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
) )
@ -17,7 +17,7 @@ type dynamicEncoder struct {
func (codec *dynamicEncoder) GetType() reflect.Kind { func (codec *dynamicEncoder) GetType() reflect.Kind {
return reflect.Interface 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) obj := encoder.valType.UnsafeIndirect(ptr)
stream.WriteVal(obj) stream.WriteVal(obj)
} }
@ -32,7 +32,7 @@ type efaceDecoder struct {
func (codec *efaceDecoder) GetType() reflect.Kind { func (codec *efaceDecoder) GetType() reflect.Kind {
return reflect.Interface 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) pObj := (*interface{})(ptr)
obj := *pObj obj := *pObj
if obj == nil { if obj == nil {
@ -46,7 +46,7 @@ func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
} }
ptrType := typ.(*reflect2.UnsafePtrType) ptrType := typ.(*reflect2.UnsafePtrType)
ptrElemType := ptrType.Elem() ptrElemType := ptrType.Elem()
if extra.WhatIsNext() == core.NilValue { if extra.WhatIsNext() == codecore.NilValue {
if ptrElemType.Kind() != reflect.Ptr { if ptrElemType.Kind() != reflect.Ptr {
extra.ReadNil() extra.ReadNil()
*pObj = nil *pObj = nil
@ -69,7 +69,7 @@ type ifaceDecoder struct {
func (codec *ifaceDecoder) GetType() reflect.Kind { func (codec *ifaceDecoder) GetType() reflect.Kind {
return reflect.Interface 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() { if extra.ReadNil() {
decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew()) decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew())
return return

View File

@ -4,19 +4,19 @@ import (
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
"sort"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "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) mapType := typ.(*reflect2.UnsafeMapType)
keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()) keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key())
elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem()) elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem())
return &mapDecoder{ return &mapDecoder{
codec: ctx.ICodec,
mapType: mapType, mapType: mapType,
keyType: mapType.Key(), keyType: mapType.Key(),
elemType: mapType.Elem(), 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) 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{ return &mapEncoder{
codec: ctx.ICodec,
mapType: mapType, mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()), keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()),
elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()), 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() { switch typ.Kind() {
case reflect.String: case reflect.String:
return DecoderOfType(ctx, reflect2.DefaultTypeOfKind(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() { switch typ.Kind() {
case reflect.String: case reflect.String:
return EncoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) return EncoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
@ -77,17 +83,72 @@ func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
} }
//Map-------------------------------------------------------------------------------------------------------------------------------------- //Map--------------------------------------------------------------------------------------------------------------------------------------
type mapEncoder struct { type sortKeysMapEncoder struct {
codec core.ICodec
mapType *reflect2.UnsafeMapType mapType *reflect2.UnsafeMapType
keyEncoder core.IEncoder keyEncoder codecore.IEncoder
elemEncoder core.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 { func (this *mapEncoder) GetType() reflect.Kind {
return reflect.Map 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 { if *(*unsafe.Pointer)(ptr) == nil {
stream.WriteNil() stream.WriteNil()
return return
@ -106,14 +167,17 @@ func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteObjectEnd() 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) ret = make(map[string]string)
var ( var (
k, v string k, v string
) )
keystream := w.GetWriter()
keystream := this.codec.BorrowStream() elemstream := w.GetWriter()
elemstream := this.codec.BorrowStream() defer func() {
w.PutWriter(keystream)
w.PutWriter(elemstream)
}()
iter := this.mapType.UnsafeIterate(ptr) iter := this.mapType.UnsafeIterate(ptr)
for i := 0; iter.HasNext(); i++ { for i := 0; iter.HasNext(); i++ {
key, elem := iter.UnsafeNext() key, elem := iter.UnsafeNext()
@ -138,8 +202,8 @@ func (this *mapEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]stri
v = *((*string)(elem)) v = *((*string)(elem))
} }
ret[k] = v ret[k] = v
keystream.Reset(512) keystream.Reset()
elemstream.Reset(512) elemstream.Reset()
} }
return return
} }
@ -150,18 +214,17 @@ func (this *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
type mapDecoder struct { type mapDecoder struct {
codec core.ICodec
mapType *reflect2.UnsafeMapType mapType *reflect2.UnsafeMapType
keyType reflect2.Type keyType reflect2.Type
elemType reflect2.Type elemType reflect2.Type
keyDecoder core.IDecoder keyDecoder codecore.IDecoder
elemDecoder core.IDecoder elemDecoder codecore.IDecoder
} }
func (codec *mapDecoder) GetType() reflect.Kind { func (codec *mapDecoder) GetType() reflect.Kind {
return reflect.Map 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 mapType := this.mapType
if extra.ReadNil() { if extra.ReadNil() {
*(*unsafe.Pointer)(ptr) = nil *(*unsafe.Pointer)(ptr) = nil
@ -200,9 +263,13 @@ func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
} }
//解码对象从MapJson 中 //解码对象从MapJson 中
func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) { func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) {
keyext := this.codec.BorrowExtractor([]byte{}) keyext := r.GetReader([]byte{})
elemext := this.codec.BorrowExtractor([]byte{}) elemext := r.GetReader([]byte{})
defer func() {
r.PutReader(keyext)
r.PutReader(keyext)
}()
for k, v := range extra { for k, v := range extra {
key := this.keyType.UnsafeNew() key := this.keyType.UnsafeNew()
if this.keyDecoder.GetType() != reflect.String { if this.keyDecoder.GetType() != reflect.String {
@ -233,13 +300,13 @@ func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]st
//NumericMap------------------------------------------------------------------------------------------------------------------------------- //NumericMap-------------------------------------------------------------------------------------------------------------------------------
type numericMapKeyDecoder struct { type numericMapKeyDecoder struct {
decoder core.IDecoder decoder codecore.IDecoder
} }
func (this *numericMapKeyDecoder) GetType() reflect.Kind { func (this *numericMapKeyDecoder) GetType() reflect.Kind {
return this.decoder.GetType() 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() { if !extra.ReadKeyStart() {
return return
} }
@ -250,13 +317,13 @@ func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtract
} }
type numericMapKeyEncoder struct { type numericMapKeyEncoder struct {
encoder core.IEncoder encoder codecore.IEncoder
} }
func (this *numericMapKeyEncoder) GetType() reflect.Kind { func (this *numericMapKeyEncoder) GetType() reflect.Kind {
return this.encoder.GetType() 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() stream.WriteKeyStart()
this.encoder.Encode(ptr, stream) this.encoder.Encode(ptr, stream)
stream.WriteKeyEnd() stream.WriteKeyEnd()
@ -268,7 +335,7 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
//------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------
type dynamicMapKeyEncoder struct { type dynamicMapKeyEncoder struct {
ctx *core.Ctx ctx *codecore.Ctx
valType reflect2.Type valType reflect2.Type
} }
@ -276,7 +343,7 @@ func (this *dynamicMapKeyEncoder) GetType() reflect.Kind {
return reflect.Interface 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) obj := this.valType.UnsafeIndirect(ptr)
encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) 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) obj := this.valType.UnsafeIndirect(ptr)
return encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) 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 }

View File

@ -5,14 +5,14 @@ import (
"strconv" "strconv"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
) )
const ptrSize = 32 << uintptr(^uintptr(0)>>63) //计算int的大小 是32 还是64 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() typeName := typ.String()
switch typ.Kind() { switch typ.Kind() {
case reflect.String: case reflect.String:
@ -103,7 +103,7 @@ func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
return nil 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() typeName := typ.String()
kind := typ.Kind() kind := typ.Kind()
switch kind { switch kind {
@ -201,11 +201,11 @@ type stringCodec struct {
func (codec *stringCodec) GetType() reflect.Kind { func (codec *stringCodec) GetType() reflect.Kind {
return reflect.String 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() *((*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)) str := *((*string)(ptr))
stream.WriteString(str) stream.WriteString(str)
} }
@ -221,13 +221,13 @@ func (codec *int8Codec) GetType() reflect.Kind {
return reflect.Int8 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() { if !extra.ReadNil() {
*((*int8)(ptr)) = extra.ReadInt8() *((*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))) stream.WriteInt8(*((*int8)(ptr)))
} }
@ -241,13 +241,13 @@ type int16Codec struct {
func (codec *int16Codec) GetType() reflect.Kind { func (codec *int16Codec) GetType() reflect.Kind {
return reflect.Int16 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() { if !extra.ReadNil() {
*((*int16)(ptr)) = extra.ReadInt16() *((*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))) stream.WriteInt16(*((*int16)(ptr)))
} }
@ -261,13 +261,13 @@ type int32Codec struct {
func (codec *int32Codec) GetType() reflect.Kind { func (codec *int32Codec) GetType() reflect.Kind {
return reflect.Int32 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() { if !extra.ReadNil() {
*((*int32)(ptr)) = extra.ReadInt32() *((*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))) stream.WriteInt32(*((*int32)(ptr)))
} }
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool { func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
@ -280,13 +280,13 @@ type int64Codec struct {
func (codec *int64Codec) GetType() reflect.Kind { func (codec *int64Codec) GetType() reflect.Kind {
return reflect.Int64 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() { if !extra.ReadNil() {
*((*int64)(ptr)) = extra.ReadInt64() *((*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))) stream.WriteInt64(*((*int64)(ptr)))
} }
@ -300,13 +300,13 @@ type uint8Codec struct {
func (codec *uint8Codec) GetType() reflect.Kind { func (codec *uint8Codec) GetType() reflect.Kind {
return reflect.Uint8 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() { if !extra.ReadNil() {
*((*uint8)(ptr)) = extra.ReadUint8() *((*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))) stream.WriteUint8(*((*uint8)(ptr)))
} }
@ -320,13 +320,13 @@ type uint16Codec struct {
func (codec *uint16Codec) GetType() reflect.Kind { func (codec *uint16Codec) GetType() reflect.Kind {
return reflect.Uint16 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() { if !extra.ReadNil() {
*((*uint16)(ptr)) = extra.ReadUint16() *((*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))) stream.WriteUint16(*((*uint16)(ptr)))
} }
@ -340,13 +340,13 @@ type uint32Codec struct {
func (codec *uint32Codec) GetType() reflect.Kind { func (codec *uint32Codec) GetType() reflect.Kind {
return reflect.Uint32 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() { if !extra.ReadNil() {
*((*uint32)(ptr)) = extra.ReadUint32() *((*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))) stream.WriteUint32(*((*uint32)(ptr)))
} }
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool { func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
@ -359,13 +359,13 @@ type uint64Codec struct {
func (codec *uint64Codec) GetType() reflect.Kind { func (codec *uint64Codec) GetType() reflect.Kind {
return reflect.Uint64 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() { if !extra.ReadNil() {
*((*uint64)(ptr)) = extra.ReadUint64() *((*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))) stream.WriteUint64(*((*uint64)(ptr)))
} }
@ -379,13 +379,13 @@ type float32Codec struct {
func (codec *float32Codec) GetType() reflect.Kind { func (codec *float32Codec) GetType() reflect.Kind {
return reflect.Float32 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() { if !extra.ReadNil() {
*((*float32)(ptr)) = extra.ReadFloat32() *((*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))) stream.WriteFloat32(*((*float32)(ptr)))
} }
@ -399,13 +399,13 @@ type float64Codec struct {
func (codec *float64Codec) GetType() reflect.Kind { func (codec *float64Codec) GetType() reflect.Kind {
return reflect.Float64 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() { if !extra.ReadNil() {
*((*float64)(ptr)) = extra.ReadFloat64() *((*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))) stream.WriteFloat64(*((*float64)(ptr)))
} }
@ -419,13 +419,13 @@ type boolCodec struct {
func (codec *boolCodec) GetType() reflect.Kind { func (codec *boolCodec) GetType() reflect.Kind {
return reflect.Bool 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() { if !extra.ReadNil() {
*((*bool)(ptr)) = extra.ReadBool() *((*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))) stream.WriteBool(*((*bool)(ptr)))
} }

View File

@ -5,19 +5,19 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "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) ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem() elemType := ptrType.Elem()
decoder := DecoderOfType(ctx, elemType) decoder := DecoderOfType(ctx, elemType)
return &OptionalDecoder{elemType, decoder} 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) ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem() elemType := ptrType.Elem()
elemEncoder := EncoderOfType(ctx, elemType) elemEncoder := EncoderOfType(ctx, elemType)
@ -28,13 +28,13 @@ func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
//Optional-------------------------------------------------------------------------------------------------------------------- //Optional--------------------------------------------------------------------------------------------------------------------
type OptionalDecoder struct { type OptionalDecoder struct {
ValueType reflect2.Type ValueType reflect2.Type
ValueDecoder core.IDecoder ValueDecoder codecore.IDecoder
} }
func (this *OptionalDecoder) GetType() reflect.Kind { func (this *OptionalDecoder) GetType() reflect.Kind {
return this.ValueDecoder.GetType() 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() { if extra.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil *((*unsafe.Pointer)(ptr)) = nil
} else { } 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) { func (this *OptionalDecoder) DecodeForMapJson(ptr unsafe.Pointer, r codecore.IReader, extra map[string]string) (err error) {
if decoderMapJson, ok := this.ValueDecoder.(core.IDecoderMapJson); !ok { if decoderMapJson, ok := this.ValueDecoder.(codecore.IDecoderMapJson); !ok {
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueDecoder) err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueDecoder)
return return
} else { } else {
return decoderMapJson.DecodeForMapJson(ptr, extra) return decoderMapJson.DecodeForMapJson(ptr, r, extra)
} }
} }
type OptionalEncoder struct { type OptionalEncoder struct {
ValueEncoder core.IEncoder ValueEncoder codecore.IEncoder
} }
func (this *OptionalEncoder) GetType() reflect.Kind { func (this *OptionalEncoder) GetType() reflect.Kind {
return this.ValueEncoder.GetType() 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 { if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil() stream.WriteNil()
} else { } else {
@ -76,8 +76,8 @@ func (this *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil return *((*unsafe.Pointer)(ptr)) == nil
} }
func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) { func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer, w codecore.IWriter) (ret map[string]string, err error) {
if encoderMapJson, ok := this.ValueEncoder.(core.IEncoderMapJson); !ok { if encoderMapJson, ok := this.ValueEncoder.(codecore.IEncoderMapJson); !ok {
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueEncoder) err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueEncoder)
return return
} else { } else {
@ -85,17 +85,17 @@ func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string
err = fmt.Errorf("encoder ptr is nil") err = fmt.Errorf("encoder ptr is nil")
return return
} else { } else {
return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr))) return encoderMapJson.EncodeToMapJson(*((*unsafe.Pointer)(ptr)), w)
} }
} }
} }
//reference-------------------------------------------------------------------------------------------------------------------- //reference--------------------------------------------------------------------------------------------------------------------
type referenceEncoder struct { 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) this.encoder.Encode(unsafe.Pointer(&ptr), stream)
} }
@ -104,23 +104,23 @@ func (this *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
type referenceDecoder struct { 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) this.decoder.Decode(unsafe.Pointer(&ptr), extra)
} }
//dereference-------------------------------------------------------------------------------------------------------------------- //dereference--------------------------------------------------------------------------------------------------------------------
type dereferenceDecoder struct { type dereferenceDecoder struct {
valueType reflect2.Type valueType reflect2.Type
valueDecoder core.IDecoder valueDecoder codecore.IDecoder
} }
func (this *dereferenceDecoder) GetType() reflect.Kind { func (this *dereferenceDecoder) GetType() reflect.Kind {
return this.valueDecoder.GetType() 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 { if *((*unsafe.Pointer)(ptr)) == nil {
newPtr := this.valueType.UnsafeNew() newPtr := this.valueType.UnsafeNew()
this.valueDecoder.Decode(newPtr, extra) this.valueDecoder.Decode(newPtr, extra)
@ -131,13 +131,13 @@ func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor
} }
type dereferenceEncoder struct { type dereferenceEncoder struct {
ValueEncoder core.IEncoder ValueEncoder codecore.IEncoder
} }
func (this *dereferenceEncoder) GetType() reflect.Kind { func (this *dereferenceEncoder) GetType() reflect.Kind {
return this.ValueEncoder.GetType() 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 { if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil() stream.WriteNil()
} else { } else {
@ -158,7 +158,7 @@ func (this *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
if deReferenced == nil { if deReferenced == nil {
return true return true
} }
isEmbeddedPtrNil, converted := this.ValueEncoder.(core.IsEmbeddedPtrNil) isEmbeddedPtrNil, converted := this.ValueEncoder.(codecore.IsEmbeddedPtrNil)
if !converted { if !converted {
return false return false
} }

View File

@ -7,32 +7,31 @@ import (
"reflect" "reflect"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "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) sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := DecoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem()) 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) sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem()) encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
return &sliceEncoder{ctx.ICodec, sliceType, encoder} return &sliceEncoder{sliceType, encoder}
} }
type sliceEncoder struct { type sliceEncoder struct {
codec core.ICodec
sliceType *reflect2.UnsafeSliceType sliceType *reflect2.UnsafeSliceType
elemEncoder core.IEncoder elemEncoder codecore.IEncoder
} }
func (codec *sliceEncoder) GetType() reflect.Kind { func (codec *sliceEncoder) GetType() reflect.Kind {
return reflect.Slice 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) { if this.sliceType.UnsafeIsNil(ptr) {
stream.WriteNil() stream.WriteNil()
return return
@ -60,7 +59,7 @@ func (this *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
//编码对象到json数组 //编码对象到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) { if this.sliceType.UnsafeIsNil(ptr) {
err = errors.New("val is nil") err = errors.New("val is nil")
return return
@ -70,30 +69,28 @@ func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, e
if length == 0 { if length == 0 {
return return
} }
stream := this.codec.BorrowStream()
for i := 1; i < length; i++ { for i := 1; i < length; i++ {
elemPtr := this.sliceType.UnsafeGetIndex(ptr, i) elemPtr := this.sliceType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream) this.elemEncoder.Encode(elemPtr, w)
if stream.Error() != nil && stream.Error() != io.EOF { if w.Error() != nil && w.Error() != io.EOF {
err = stream.Error() err = w.Error()
return return
} }
ret[i] = BytesToString(stream.Buffer()) ret[i] = BytesToString(w.Buffer())
stream.Reset(512) w.Reset()
} }
return return
} }
type sliceDecoder struct { type sliceDecoder struct {
codec core.ICodec
sliceType *reflect2.UnsafeSliceType sliceType *reflect2.UnsafeSliceType
elemDecoder core.IDecoder elemDecoder codecore.IDecoder
} }
func (codec *sliceDecoder) GetType() reflect.Kind { func (codec *sliceDecoder) GetType() reflect.Kind {
return reflect.Slice 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 sliceType := this.sliceType
if extra.ReadNil() { if extra.ReadNil() {
sliceType.UnsafeSetNil(ptr) 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 sliceType := this.sliceType
if data == nil { if data == nil {
err = errors.New("extra is nil") err = errors.New("extra is nil")
return return
} }
extra := this.codec.BorrowExtractor([]byte{})
sliceType.UnsafeGrow(ptr, len(data)) sliceType.UnsafeGrow(ptr, len(data))
for i, v := range data { for i, v := range data {
elemPtr := sliceType.UnsafeGetIndex(ptr, i) elemPtr := sliceType.UnsafeGetIndex(ptr, i)
extra.ResetBytes(StringToBytes(v)) r.ResetBytes(StringToBytes(v))
this.elemDecoder.Decode(elemPtr, extra) this.elemDecoder.Decode(elemPtr, r)
if extra.Error() != nil && extra.Error() != io.EOF { if r.Error() != nil && r.Error() != io.EOF {
err = extra.Error() err = r.Error()
return return
} }
} }

View File

@ -10,7 +10,7 @@ import (
"unicode" "unicode"
"unsafe" "unsafe"
"go_dreamfactory/lego/sys/codec/core" "go_dreamfactory/lego/utils/codec/codecore"
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
) )
@ -25,11 +25,11 @@ type Binding struct {
Field reflect2.StructField Field reflect2.StructField
FromNames []string FromNames []string
ToNames []string ToNames []string
Encoder core.IEncoder Encoder codecore.IEncoder
Decoder core.IDecoder 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 { type bindingTo struct {
binding *Binding binding *Binding
toName string toName string
@ -47,7 +47,7 @@ func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
if old.toName != toName { if old.toName != toName {
continue 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) 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{} bindings := map[string]*Binding{}
structDescriptor := describeStruct(ctx, typ) structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
@ -77,7 +77,7 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
bindings[fromName] = binding bindings[fromName] = binding
continue continue
} }
ignoreOld, ignoreNew := resolveConflictBinding(ctx.Options(), old, binding) ignoreOld, ignoreNew := resolveConflictBinding(ctx.Config, old, binding)
if ignoreOld { if ignoreOld {
delete(bindings, fromName) delete(bindings, fromName)
} }
@ -91,25 +91,25 @@ func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
fields[k] = binding.Decoder.(*structFieldDecoder) fields[k] = binding.Decoder.(*structFieldDecoder)
} }
if !ctx.Options().CaseSensitive { if !ctx.Config.CaseSensitive {
for k, binding := range bindings { for k, binding := range bindings {
if _, found := fields[strings.ToLower(k)]; !found { if _, found := fields[strings.ToLower(k)]; !found {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) 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) structType := typ.(*reflect2.UnsafeStructType)
embeddedBindings := []*Binding{} embeddedBindings := []*Binding{}
bindings := []*Binding{} bindings := []*Binding{}
for i := 0; i < structType.NumField(); i++ { for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i) field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.Options().TagKey) tag, hastag := field.Tag().Lookup(ctx.Config.TagKey)
if ctx.Options().OnlyTaggedField && !hastag && !field.Anonymous() { if ctx.Config.OnlyTaggedField && !hastag && !field.Anonymous() {
continue continue
} }
if tag == "-" || field.Name() == "_" { if tag == "-" || field.Name() == "_" {
@ -160,22 +160,22 @@ func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor {
return createStructDescriptor(ctx, typ, bindings, embeddedBindings) 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{ structDescriptor := &StructDescriptor{
Type: typ, Type: typ,
Fields: bindings, Fields: bindings,
} }
processTags(structDescriptor, ctx.ICodec) processTags(structDescriptor, ctx.Config)
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings) sort.Sort(allBindings)
structDescriptor.Fields = allBindings structDescriptor.Fields = allBindings
return structDescriptor return structDescriptor
} }
func processTags(structDescriptor *StructDescriptor, codec core.ICodec) { func processTags(structDescriptor *StructDescriptor, config *codecore.Config) {
for _, binding := range structDescriptor.Fields { for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false 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:] { for _, tagPart := range tagParts[1:] {
if tagPart == "omitempty" { if tagPart == "omitempty" {
shouldOmitEmpty = true shouldOmitEmpty = true
@ -206,17 +206,9 @@ func calcFieldNames(originalFieldName string, tagProvidedFieldName string, whole
return fieldNames return fieldNames
} }
func createStructDecoder(codec core.ICodec, typ reflect2.Type, fields map[string]*structFieldDecoder) core.IDecoder { func resolveConflictBinding(config *codecore.Config, old, new *Binding) (ignoreOld, ignoreNew bool) {
if codec.Options().DisallowUnknownFields { newTagged := new.Field.Tag().Get(config.TagKey) != ""
return &structDecoder{typ: typ, fields: fields, disallowUnknownFields: true} oldTagged := old.Field.Tag().Get(config.TagKey) != ""
} 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) != ""
if newTagged { if newTagged {
if oldTagged { if oldTagged {
if len(old.levels) > len(new.levels) { if len(old.levels) > len(new.levels) {
@ -245,7 +237,6 @@ func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ig
//结构对象 编解码----------------------------------------------------------------------------------------------------------------------- //结构对象 编解码-----------------------------------------------------------------------------------------------------------------------
type structEncoder struct { type structEncoder struct {
codec core.ICodec
typ reflect2.Type typ reflect2.Type
fields []structFieldTo fields []structFieldTo
} }
@ -253,7 +244,7 @@ type structEncoder struct {
func (codec *structEncoder) GetType() reflect.Kind { func (codec *structEncoder) GetType() reflect.Kind {
return reflect.Struct 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() stream.WriteObjectStart()
isNotFirst := false isNotFirst := false
for _, field := range this.fields { 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) ret = make(map[string]string)
stream := this.codec.BorrowStream()
for _, field := range this.fields { for _, field := range this.fields {
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) { if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
continue continue
@ -286,13 +276,13 @@ func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]s
if field.encoder.IsEmbeddedPtrNil(ptr) { if field.encoder.IsEmbeddedPtrNil(ptr) {
continue continue
} }
stream.Reset(512) w.Reset()
field.encoder.Encode(ptr, stream) field.encoder.Encode(ptr, w)
if stream.Error() != nil && stream.Error() != io.EOF { if w.Error() != nil && w.Error() != io.EOF {
err = stream.Error() err = w.Error()
return return
} }
ret[field.toName] = BytesToString(stream.Buffer()) ret[field.toName] = BytesToString(w.Buffer())
} }
return return
} }
@ -302,68 +292,67 @@ func (this *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
} }
type structDecoder struct { type structDecoder struct {
codec core.ICodec config *codecore.Config
typ reflect2.Type typ reflect2.Type
fields map[string]*structFieldDecoder fields map[string]*structFieldDecoder
disallowUnknownFields bool
} }
func (codec *structDecoder) GetType() reflect.Kind { func (codec *structDecoder) GetType() reflect.Kind {
return reflect.Struct return reflect.Struct
} }
func (this *structDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) { func (this *structDecoder) Decode(ptr unsafe.Pointer, r codecore.IReader) {
if !extra.ReadObjectStart() { if !r.ReadObjectStart() {
return return
} }
this.decodeField(ptr, extra) this.decodeField(ptr, r)
for extra.ReadMemberSplit() { for r.ReadMemberSplit() {
this.decodeField(ptr, extra) this.decodeField(ptr, r)
} }
if extra.Error() != nil && extra.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 { if r.Error() != nil && r.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 {
extra.SetErr(fmt.Errorf("%v.%s", this.typ, extra.Error().Error())) 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 field string
var fieldDecoder *structFieldDecoder var fieldDecoder *structFieldDecoder
field = extra.ReadString() field = r.ReadString()
fieldDecoder = this.fields[field] fieldDecoder = this.fields[field]
if fieldDecoder == nil && !this.codec.Options().CaseSensitive { if fieldDecoder == nil && !this.config.CaseSensitive {
fieldDecoder = this.fields[strings.ToLower(field)] fieldDecoder = this.fields[strings.ToLower(field)]
} }
if fieldDecoder == nil { if fieldDecoder == nil {
if this.disallowUnknownFields { if this.config.DisallowUnknownFields {
msg := "found unknown field: " + field msg := "found unknown field: " + field
extra.SetErr(fmt.Errorf("decodeField %s", msg)) r.SetErr(fmt.Errorf("decodeField %s", msg))
return return
} }
if !extra.ReadKVSplit() { if !r.ReadKVSplit() {
return return
} }
extra.Skip() //跳过一个数据单元 r.Skip() //跳过一个数据单元
return return
} }
if !extra.ReadKVSplit() { if !r.ReadKVSplit() {
return return
} }
fieldDecoder.Decode(ptr, extra) fieldDecoder.Decode(ptr, r)
} }
//解码对象从MapJson 中 //解码对象从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 var fieldDecoder *structFieldDecoder
ext := this.codec.BorrowExtractor([]byte{}) ext := r.GetReader([]byte{})
for k, v := range extra { for k, v := range extra {
fieldDecoder = this.fields[k] fieldDecoder = this.fields[k]
if fieldDecoder == nil && !this.codec.Options().CaseSensitive { if fieldDecoder == nil && !this.config.CaseSensitive {
fieldDecoder = this.fields[strings.ToLower(k)] fieldDecoder = this.fields[strings.ToLower(k)]
} }
if fieldDecoder == nil { if fieldDecoder == nil {
if this.disallowUnknownFields { if this.config.DisallowUnknownFields {
err = errors.New("found unknown field: " + k) err = errors.New("found unknown field: " + k)
return return
} }
@ -386,18 +375,18 @@ type structFieldTo struct {
} }
type structFieldEncoder struct { type structFieldEncoder struct {
field reflect2.StructField field reflect2.StructField
fieldEncoder core.IEncoder fieldEncoder codecore.IEncoder
omitempty bool omitempty bool
} }
func (this *structFieldEncoder) GetType() reflect.Kind { func (this *structFieldEncoder) GetType() reflect.Kind {
return this.fieldEncoder.GetType() 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) fieldPtr := encoder.field.UnsafeGet(ptr)
encoder.fieldEncoder.Encode(fieldPtr, stream) encoder.fieldEncoder.Encode(fieldPtr, w)
if stream.Error() != nil && stream.Error() != io.EOF { if w.Error() != nil && w.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error().Error())) 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 { func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
isEmbeddedPtrNil, converted := encoder.fieldEncoder.(core.IsEmbeddedPtrNil) isEmbeddedPtrNil, converted := encoder.fieldEncoder.(codecore.IsEmbeddedPtrNil)
if !converted { if !converted {
return false return false
} }
@ -417,17 +406,17 @@ func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
type structFieldDecoder struct { type structFieldDecoder struct {
field reflect2.StructField field reflect2.StructField
fieldDecoder core.IDecoder fieldDecoder codecore.IDecoder
} }
func (this *structFieldDecoder) GetType() reflect.Kind { func (this *structFieldDecoder) GetType() reflect.Kind {
return this.fieldDecoder.GetType() 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) fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, extra) decoder.fieldDecoder.Decode(fieldPtr, r)
if extra.Error() != nil && extra.Error() != io.EOF { if r.Error() != nil && r.Error() != io.EOF {
extra.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), extra.Error().Error())) 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 { func (codec *emptyStructEncoder) GetType() reflect.Kind {
return reflect.Struct return reflect.Struct
} }
func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) { func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, w codecore.IWriter) {
stream.WriteEmptyObject() w.WriteEmptyObject()
} }
func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {

View 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
}

View File

@ -1,30 +1,21 @@
package render package json
import ( import (
"fmt" "fmt"
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/sys/codec/utils"
"io" "io"
"math/big" "math/big"
"reflect" "reflect"
"unicode/utf16" "unicode/utf16"
"go_dreamfactory/lego/utils/codec"
"go_dreamfactory/lego/utils/codec/codecore"
"go_dreamfactory/lego/utils/codec/utils"
"github.com/modern-go/reflect2" "github.com/modern-go/reflect2"
) )
func NewExtractor(codec core.ICodec) *JsonExtractor { type JsonReader struct {
return &JsonExtractor{
codec: codec,
buf: nil,
head: 0,
tail: 0,
depth: 0,
err: nil,
}
}
type JsonExtractor struct {
codec core.ICodec
buf []byte buf []byte
head int head int
tail int tail int
@ -32,17 +23,29 @@ type JsonExtractor struct {
err error 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 depth := this.depth
cacheKey := reflect2.RTypeOf(obj) cacheKey := reflect2.RTypeOf(obj)
decoder := this.codec.GetDecoderFromCache(cacheKey) decoder := codec.GetDecoder(cacheKey)
if decoder == nil { if decoder == nil {
typ := reflect2.TypeOf(obj) typ := reflect2.TypeOf(obj)
if typ == nil || typ.Kind() != reflect.Ptr { if typ == nil || typ.Kind() != reflect.Ptr {
this.reportError("ReadVal", "can only unmarshal into pointer") this.reportError("ReadVal", "can only unmarshal into pointer")
return return
} }
decoder = this.codec.DecoderOf(typ) decoder = codec.DecoderOf(typ, defconf)
} }
ptr := reflect2.PtrOf(obj) ptr := reflect2.PtrOf(obj)
if ptr == nil { if ptr == nil {
@ -55,35 +58,35 @@ func (this *JsonExtractor) ReadVal(obj interface{}) {
return return
} }
} }
func (this *JsonExtractor) WhatIsNext() core.ValueType { func (this *JsonReader) WhatIsNext() codecore.ValueType {
valueType := valueTypes[this.nextToken()] valueType := valueTypes[this.nextToken()]
this.unreadByte() this.unreadByte()
return valueType return valueType
} }
func (this *JsonExtractor) Read() interface{} { func (this *JsonReader) Read() interface{} {
valueType := this.WhatIsNext() valueType := this.WhatIsNext()
switch valueType { switch valueType {
case core.StringValue: case codecore.StringValue:
return this.ReadString() return this.ReadString()
case core.NumberValue: case codecore.NumberValue:
return this.ReadFloat64() return this.ReadFloat64()
case core.NilValue: case codecore.NilValue:
this.skipFourBytes('n', 'u', 'l', 'l') this.skipFourBytes('n', 'u', 'l', 'l')
return nil return nil
case core.BoolValue: case codecore.BoolValue:
return this.ReadBool() return this.ReadBool()
case core.ArrayValue: case codecore.ArrayValue:
arr := []interface{}{} arr := []interface{}{}
this.ReadArrayCB(func(extra core.IExtractor) bool { this.ReadArrayCB(func(extra codecore.IReader) bool {
var elem interface{} var elem interface{}
extra.ReadVal(&elem) extra.ReadVal(&elem)
arr = append(arr, elem) arr = append(arr, elem)
return true return true
}) })
return arr return arr
case core.ObjectValue: case codecore.ObjectValue:
obj := map[string]interface{}{} 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{} var elem interface{}
this.ReadVal(&elem) this.ReadVal(&elem)
obj[field] = elem obj[field] = elem
@ -95,7 +98,7 @@ func (this *JsonExtractor) Read() interface{} {
return nil return nil
} }
} }
func (this *JsonExtractor) ReadNil() (ret bool) { func (this *JsonReader) ReadNil() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == 'n' { if c == 'n' {
this.skipThreeBytes('u', 'l', 'l') // null this.skipThreeBytes('u', 'l', 'l') // null
@ -104,7 +107,7 @@ func (this *JsonExtractor) ReadNil() (ret bool) {
this.unreadByte() this.unreadByte()
return false return false
} }
func (this *JsonExtractor) ReadArrayStart() (ret bool) { func (this *JsonReader) ReadArrayStart() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == '[' { if c == '[' {
return true return true
@ -112,7 +115,7 @@ func (this *JsonExtractor) ReadArrayStart() (ret bool) {
this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c})) this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) { func (this *JsonReader) CheckNextIsArrayEnd() (ret bool) {
c := this.nextToken() c := this.nextToken()
this.unreadByte() this.unreadByte()
if c == ']' { if c == ']' {
@ -120,7 +123,7 @@ func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) {
} }
return return
} }
func (this *JsonExtractor) ReadArrayEnd() (ret bool) { func (this *JsonReader) ReadArrayEnd() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == ']' { if c == ']' {
return true return true
@ -128,7 +131,7 @@ func (this *JsonExtractor) ReadArrayEnd() (ret bool) {
this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c})) this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ReadObjectStart() (ret bool) { func (this *JsonReader) ReadObjectStart() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == '{' { if c == '{' {
return this.incrementDepth() return this.incrementDepth()
@ -136,7 +139,7 @@ func (this *JsonExtractor) ReadObjectStart() (ret bool) {
this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c})) this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) { func (this *JsonReader) CheckNextIsObjectEnd() (ret bool) {
c := this.nextToken() c := this.nextToken()
this.unreadByte() this.unreadByte()
if c == '}' { if c == '}' {
@ -144,7 +147,7 @@ func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) {
} }
return return
} }
func (this *JsonExtractor) ReadObjectEnd() (ret bool) { func (this *JsonReader) ReadObjectEnd() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == '}' { if c == '}' {
return this.decrementDepth() return this.decrementDepth()
@ -152,7 +155,7 @@ func (this *JsonExtractor) ReadObjectEnd() (ret bool) {
this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c})) this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ReadMemberSplit() (ret bool) { func (this *JsonReader) ReadMemberSplit() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == ',' { if c == ',' {
return true return true
@ -160,7 +163,7 @@ func (this *JsonExtractor) ReadMemberSplit() (ret bool) {
this.unreadByte() this.unreadByte()
return return
} }
func (this *JsonExtractor) ReadKVSplit() (ret bool) { func (this *JsonReader) ReadKVSplit() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == ':' { if c == ':' {
return true return true
@ -168,7 +171,7 @@ func (this *JsonExtractor) ReadKVSplit() (ret bool) {
this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c})) this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ReadKeyStart() (ret bool) { func (this *JsonReader) ReadKeyStart() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == '"' { if c == '"' {
return true return true
@ -176,7 +179,7 @@ func (this *JsonExtractor) ReadKeyStart() (ret bool) {
this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c})) this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ReadKeyEnd() (ret bool) { func (this *JsonReader) ReadKeyEnd() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == '"' { if c == '"' {
return true return true
@ -184,7 +187,7 @@ func (this *JsonExtractor) ReadKeyEnd() (ret bool) {
this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c})) this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) Skip() { func (this *JsonReader) Skip() {
c := this.nextToken() c := this.nextToken()
switch c { switch c {
case '"': case '"':
@ -209,7 +212,7 @@ func (this *JsonExtractor) Skip() {
return return
} }
} }
func (this *JsonExtractor) ReadBool() (ret bool) { func (this *JsonReader) ReadBool() (ret bool) {
c := this.nextToken() c := this.nextToken()
if c == 't' { if c == 't' {
this.skipThreeBytes('r', 'u', 'e') 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})) this.reportError("ReadBool", "expect t or f, but found "+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ReadInt8() (ret int8) { func (this *JsonReader) ReadInt8() (ret int8) {
var ( var (
n int n int
err error err error
@ -234,7 +237,7 @@ func (this *JsonExtractor) ReadInt8() (ret int8) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadInt16() (ret int16) { func (this *JsonReader) ReadInt16() (ret int16) {
var ( var (
n int n int
err error err error
@ -246,7 +249,7 @@ func (this *JsonExtractor) ReadInt16() (ret int16) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadInt32() (ret int32) { func (this *JsonReader) ReadInt32() (ret int32) {
var ( var (
n int n int
err error err error
@ -258,7 +261,7 @@ func (this *JsonExtractor) ReadInt32() (ret int32) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadInt64() (ret int64) { func (this *JsonReader) ReadInt64() (ret int64) {
var ( var (
n int n int
err error err error
@ -270,7 +273,7 @@ func (this *JsonExtractor) ReadInt64() (ret int64) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadUint8() (ret uint8) { func (this *JsonReader) ReadUint8() (ret uint8) {
var ( var (
n int n int
err error err error
@ -282,7 +285,7 @@ func (this *JsonExtractor) ReadUint8() (ret uint8) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadUint16() (ret uint16) { func (this *JsonReader) ReadUint16() (ret uint16) {
var ( var (
n int n int
err error err error
@ -294,7 +297,7 @@ func (this *JsonExtractor) ReadUint16() (ret uint16) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadUint32() (ret uint32) { func (this *JsonReader) ReadUint32() (ret uint32) {
var ( var (
n int n int
err error err error
@ -306,7 +309,7 @@ func (this *JsonExtractor) ReadUint32() (ret uint32) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadUint64() (ret uint64) { func (this *JsonReader) ReadUint64() (ret uint64) {
var ( var (
n int n int
err error err error
@ -318,7 +321,7 @@ func (this *JsonExtractor) ReadUint64() (ret uint64) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadFloat32() (ret float32) { func (this *JsonReader) ReadFloat32() (ret float32) {
var ( var (
n int n int
err error err error
@ -330,7 +333,7 @@ func (this *JsonExtractor) ReadFloat32() (ret float32) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadFloat64() (ret float64) { func (this *JsonReader) ReadFloat64() (ret float64) {
var ( var (
n int n int
err error err error
@ -342,7 +345,7 @@ func (this *JsonExtractor) ReadFloat64() (ret float64) {
this.head += n this.head += n
return return
} }
func (this *JsonExtractor) ReadString() (ret string) { func (this *JsonReader) ReadString() (ret string) {
c := this.nextToken() c := this.nextToken()
if c == '"' { if c == '"' {
for i := this.head; i < this.tail; i++ { 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})) this.reportError("ReadString", `expects " or n, but found `+string([]byte{c}))
return return
} }
func (this *JsonExtractor) ResetBytes(d []byte) { func (this *JsonReader) ResetBytes(d []byte) {
this.buf = d this.buf = d
this.head = 0 this.head = 0
this.tail = len(d) this.tail = len(d)
} }
func (this *JsonExtractor) Error() error { func (this *JsonReader) Error() error {
return this.err return this.err
} }
func (this *JsonExtractor) SetErr(err error) { func (this *JsonReader) SetErr(err error) {
this.err = err this.err = err
} }
//----------------------------------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------------------------------
func (this *JsonExtractor) readByte() (ret byte) { func (this *JsonReader) readByte() (ret byte) {
if this.head == this.tail { if this.head == this.tail {
return 0 return 0
} }
@ -388,7 +391,7 @@ func (this *JsonExtractor) readByte() (ret byte) {
this.head++ this.head++
return ret return ret
} }
func (this *JsonExtractor) readStringSlowPath() (ret string) { func (this *JsonReader) readStringSlowPath() (ret string) {
var str []byte var str []byte
var c byte var c byte
for this.err == nil { for this.err == nil {
@ -406,7 +409,7 @@ func (this *JsonExtractor) readStringSlowPath() (ret string) {
this.reportError("readStringSlowPath", "unexpected end of input") this.reportError("readStringSlowPath", "unexpected end of input")
return return
} }
func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte { func (this *JsonReader) readEscapedChar(c byte, str []byte) []byte {
switch c { switch c {
case 'u': case 'u':
r := this.readU4() r := this.readU4()
@ -465,7 +468,7 @@ func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte {
} }
return str return str
} }
func (this *JsonExtractor) readU4() (ret rune) { func (this *JsonReader) readU4() (ret rune) {
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c := this.readByte() c := this.readByte()
if this.err != nil { if this.err != nil {
@ -484,7 +487,7 @@ func (this *JsonExtractor) readU4() (ret rune) {
} }
return ret return ret
} }
func (this *JsonExtractor) nextToken() byte { func (this *JsonReader) nextToken() byte {
for i := this.head; i < this.tail; i++ { for i := this.head; i < this.tail; i++ {
c := this.buf[i] c := this.buf[i]
switch c { switch c {
@ -496,14 +499,14 @@ func (this *JsonExtractor) nextToken() byte {
} }
return 0 return 0
} }
func (this *JsonExtractor) unreadByte() { func (this *JsonReader) unreadByte() {
if this.err != nil { if this.err != nil {
return return
} }
this.head-- this.head--
return return
} }
func (this *JsonExtractor) skipNumber() { func (this *JsonReader) skipNumber() {
if !this.trySkipNumber() { if !this.trySkipNumber() {
this.unreadByte() this.unreadByte()
if this.err != nil && this.err != io.EOF { 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 ( var (
n int n int
err error err error
@ -528,7 +531,7 @@ func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) {
this.head += n this.head += n
return return
} }
func (iter *JsonExtractor) trySkipNumber() bool { func (iter *JsonReader) trySkipNumber() bool {
dotFound := false dotFound := false
for i := iter.head; i < iter.tail; i++ { for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i] c := iter.buf[i]
@ -564,13 +567,13 @@ func (iter *JsonExtractor) trySkipNumber() bool {
} }
return false return false
} }
func (this *JsonExtractor) skipString() { func (this *JsonReader) skipString() {
if !this.trySkipString() { if !this.trySkipString() {
this.unreadByte() this.unreadByte()
this.ReadString() this.ReadString()
} }
} }
func (this *JsonExtractor) trySkipString() bool { func (this *JsonReader) trySkipString() bool {
for i := this.head; i < this.tail; i++ { for i := this.head; i < this.tail; i++ {
c := this.buf[i] c := this.buf[i]
if c == '"' { if c == '"' {
@ -586,21 +589,21 @@ func (this *JsonExtractor) trySkipString() bool {
} }
return false return false
} }
func (this *JsonExtractor) skipObject() { func (this *JsonReader) skipObject() {
this.unreadByte() this.unreadByte()
this.ReadObjectCB(func(extra core.IExtractor, field string) bool { this.ReadObjectCB(func(extra codecore.IReader, field string) bool {
extra.Skip() extra.Skip()
return true return true
}) })
} }
func (this *JsonExtractor) skipArray() { func (this *JsonReader) skipArray() {
this.unreadByte() this.unreadByte()
this.ReadArrayCB(func(extra core.IExtractor) bool { this.ReadArrayCB(func(extra codecore.IReader) bool {
extra.Skip() extra.Skip()
return true return true
}) })
} }
func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) { func (this *JsonReader) skipThreeBytes(b1, b2, b3 byte) {
if this.readByte() != b1 { if this.readByte() != b1 {
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
return return
@ -614,7 +617,7 @@ func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) {
return return
} }
} }
func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) { func (this *JsonReader) skipFourBytes(b1, b2, b3, b4 byte) {
if this.readByte() != b1 { if this.readByte() != b1 {
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
return return
@ -632,7 +635,7 @@ func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) {
return return
} }
} }
func (this *JsonExtractor) reportError(operation string, msg string) { func (this *JsonReader) reportError(operation string, msg string) {
if this.err != nil { if this.err != nil {
if this.err != io.EOF { if this.err != io.EOF {
return 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|...", this.err = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
operation, msg, this.head-peekStart, parsing, context) operation, msg, this.head-peekStart, parsing, context)
} }
func (this *JsonExtractor) incrementDepth() (success bool) { func (this *JsonReader) incrementDepth() (success bool) {
this.depth++ this.depth++
if this.depth <= maxDepth { if this.depth <= maxDepth {
return true return true
@ -667,7 +670,7 @@ func (this *JsonExtractor) incrementDepth() (success bool) {
this.reportError("incrementDepth", "exceeded max depth") this.reportError("incrementDepth", "exceeded max depth")
return false return false
} }
func (this *JsonExtractor) decrementDepth() (success bool) { func (this *JsonReader) decrementDepth() (success bool) {
this.depth-- this.depth--
if this.depth >= 0 { if this.depth >= 0 {
return true return true
@ -675,7 +678,7 @@ func (this *JsonExtractor) decrementDepth() (success bool) {
this.reportError("decrementDepth", "unexpected negative nesting") this.reportError("decrementDepth", "unexpected negative nesting")
return false 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() c := iter.nextToken()
var field string var field string
if c == '{' { if c == '{' {
@ -729,7 +732,7 @@ func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) b
return false 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() c := iter.nextToken()
if c == '{' { if c == '{' {
if !iter.incrementDepth() { if !iter.incrementDepth() {
@ -784,7 +787,7 @@ func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool
return false 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() c := iter.nextToken()
if c == '[' { if c == '[' {
if !iter.incrementDepth() { if !iter.incrementDepth() {

View 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, ' ')
}
}

View 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))
}

View 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)
}

View File

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"go_dreamfactory/comm" "go_dreamfactory/comm"
"go_dreamfactory/lego/core" "go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/redis" "go_dreamfactory/lego/sys/redis"
"go_dreamfactory/lego/utils/codec/json"
"go_dreamfactory/modules" "go_dreamfactory/modules"
"go_dreamfactory/pb" "go_dreamfactory/pb"
@ -101,7 +101,7 @@ func (this *modelChatComp) GetChatQueue(channel pb.ChatChannel, union, group, ar
result = make([]*pb.DBChat, len(cdata)) result = make([]*pb.DBChat, len(cdata))
for i, v := range cdata { for i, v := range cdata {
chat := &pb.DBChat{} chat := &pb.DBChat{}
if err = codec.UnmarshalMapJson(v, chat); err != nil { if err = json.UnmarshalMap(v, chat); err != nil {
return return
} }
result[i] = chat 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)) vs = make([]map[string]string, len(msgs))
values = make([]interface{}, len(msgs)) values = make([]interface{}, len(msgs))
for i, v := range 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) this.module.Errorf("err:%v", err)
return return
} }

View File

@ -6,11 +6,12 @@ import (
"go_dreamfactory/comm" "go_dreamfactory/comm"
"go_dreamfactory/lego/core" "go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase" "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/log"
"go_dreamfactory/lego/sys/mgo" "go_dreamfactory/lego/sys/mgo"
"go_dreamfactory/lego/sys/redis" "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/cache"
"go_dreamfactory/sys/db" "go_dreamfactory/sys/db"
"reflect" "reflect"
@ -22,6 +23,15 @@ import (
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
) )
var defconf = &codecore.Config{
SortMapKeys: true,
IndentionStep: 1,
OnlyTaggedField: false,
DisallowUnknownFields: false,
CaseSensitive: false,
TagKey: "json",
}
//Redis 自定义脚本 批量读取列表数据 //Redis 自定义脚本 批量读取列表数据
var LuaScriptgetList = ` var LuaScriptgetList = `
local key = tostring(KEYS[1]) local key = tostring(KEYS[1])
@ -374,8 +384,8 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
sType reflect2.Type sType reflect2.Type
sliceType *reflect2.UnsafeSliceType sliceType *reflect2.UnsafeSliceType
sliceelemType reflect2.Type sliceelemType reflect2.Type
decoder ccore.IDecoderMapJson decoder codecore.IDecoderMapJson
encoder ccore.IEncoderMapJson encoder codecore.IEncoderMapJson
dptr unsafe.Pointer dptr unsafe.Pointer
elemPtr unsafe.Pointer elemPtr unsafe.Pointer
n int 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) err = fmt.Errorf("MCompModel: GetList(sliceelemType non-pointer %T)", data)
return 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) err = fmt.Errorf("MCompModel: GetList(data not support MarshalMapJson %T)", data)
return return
} }
@ -416,13 +426,13 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
elemPtr = sliceType.UnsafeGetIndex(dptr, n) elemPtr = sliceType.UnsafeGetIndex(dptr, n)
if *((*unsafe.Pointer)(elemPtr)) == nil { if *((*unsafe.Pointer)(elemPtr)) == nil {
newPtr := sliceelemType.UnsafeNew() 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) log.Errorf("err:%v", err)
return return
} }
*((*unsafe.Pointer)(elemPtr)) = newPtr *((*unsafe.Pointer)(elemPtr)) = newPtr
} else { } else {
decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), v) decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetReader([]byte{}), v)
} }
n++ 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 { if c, err = this.DB.Find(core.SqlTable(this.TableName), bson.M{"uid": uid}); err != nil {
return err return err
} else { } 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) err = fmt.Errorf("MCompModel: GetList(data not support UnMarshalMapJson %T)", data)
return return
} }
@ -450,7 +460,7 @@ func (this *MCompModel) GetList(uid string, data interface{}) (err error) {
if err = c.Decode(elem); err != nil { if err = c.Decode(elem); err != nil {
return return
} }
if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr))); err != nil { if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetWriter()); err != nil {
return return
} }
key := this.ukeylist(uid, _id) key := this.ukeylist(uid, _id)
@ -668,33 +678,6 @@ func (this *MCompModel) logOpt(uid string, data interface{}, attrs ...*cache.Ope
return nil 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) { func (this *MCompModel) CleanUserRecord(uid string) (err error) {
err = this.Redis.Delete(this.ukey(uid)) err = this.Redis.Delete(this.ukey(uid))

View File

@ -1,7 +1,6 @@
package gateway package gateway
import ( import (
"fmt"
"go_dreamfactory/comm" "go_dreamfactory/comm"
"go_dreamfactory/lego/base" "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() { func (this *Gateway) Debug(msg string, args ...log.Field) {
this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) this.options.GetLog().Debug(msg, args...)
}
} }
func (this *Gateway) Infof(format string, a ...interface{}) { func (this *Gateway) Info(msg string, args ...log.Field) {
if this.options.GetDebug() { this.options.GetLog().Info(msg, args...)
this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
}
} }
func (this *Gateway) Warnf(format string, a ...interface{}) { func (this *Gateway) Print(msg string, args ...log.Field) {
if this.options.Debug { this.options.GetLog().Print(msg, args...)
this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
}
} }
func (this *Gateway) Errorf(format string, a ...interface{}) { func (this *Gateway) Warn(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Warn(msg, args...)
this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
}
} }
func (this *Gateway) Panicf(format string, a ...interface{}) { func (this *Gateway) Error(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Error(msg, args...)
this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...)
}
} }
func (this *Gateway) Fatalf(format string, a ...interface{}) { func (this *Gateway) Panic(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Panic(msg, args...)
this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.GetType())+format, a...) }
} 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...)
} }

View File

@ -43,6 +43,7 @@ func (this *ModuleBase) Init(service core.IService, module core.IModule, options
this.service = service.(base.IRPCXService) this.service = service.(base.IRPCXService)
this.module = module this.module = module
this.options = options.(IOptions) this.options = options.(IOptions)
this.options.GetLog().SetName("module." + string(module.GetType()))
return return
} }
@ -289,33 +290,68 @@ func (this *ModuleBase) DispenseRes(session comm.IUserSession, res []*cfg.Game_a
} }
//日志接口 //日志接口
func (this *ModuleBase) Debugf(format string, a ...interface{}) { func (this *ModuleBase) Debug(msg string, args ...log.Field) {
if this.options.GetDebug() { this.options.GetLog().Debug(msg, args...)
this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
}
} }
func (this *ModuleBase) Infof(format string, a ...interface{}) { func (this *ModuleBase) Info(msg string, args ...log.Field) {
if this.options.GetDebug() { this.options.GetLog().Info(msg, args...)
this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
}
} }
func (this *ModuleBase) Warnf(format string, a ...interface{}) { func (this *ModuleBase) Print(msg string, args ...log.Field) {
if this.options.GetDebug() { this.options.GetLog().Print(msg, args...)
this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
}
} }
func (this *ModuleBase) Errorf(format string, a ...interface{}) { func (this *ModuleBase) Warn(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Warn(msg, args...)
this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
}
} }
func (this *ModuleBase) Panicf(format string, a ...interface{}) { func (this *ModuleBase) Error(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Error(msg, args...)
this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...)
}
} }
func (this *ModuleBase) Fatalf(format string, a ...interface{}) { func (this *ModuleBase) Panic(msg string, args ...log.Field) {
if this.options.GetLog() != nil { this.options.GetLog().Panic(msg, args...)
this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) }
} 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...)
} }

View File

@ -1,7 +1,7 @@
package modules package modules
import ( import (
"fmt" "errors"
"go_dreamfactory/lego/core" "go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure" "go_dreamfactory/lego/utils/mapstructure"
@ -12,11 +12,11 @@ type (
IOptions interface { IOptions interface {
core.IModuleOptions core.IModuleOptions
GetDebug() bool GetDebug() bool
GetLog() log.ILog GetLog() log.ILogger
} }
Options struct { Options struct {
Debug bool //日志是否开启 Debug bool //日志是否开启
Log log.ILog Log log.ILogger
} }
) )
@ -24,7 +24,7 @@ func (this *Options) GetDebug() bool {
return this.Debug return this.Debug
} }
func (this *Options) GetLog() log.ILog { func (this *Options) GetLog() log.ILogger {
return this.Log return this.Log
} }
@ -32,12 +32,9 @@ func (this *Options) LoadConfig(settings map[string]interface{}) (err error) {
if settings != nil { if settings != nil {
err = mapstructure.Decode(settings, this) err = mapstructure.Decode(settings, this)
} }
if this.Debug && this.Log == nil {
this.Log = log.Clone() if this.Log = log.NewTurnlog(this.Debug, log.Clone("", 2)); this.Log == nil {
if this.Log == nil { err = errors.New("log is nil")
err = fmt.Errorf("Log is nil")
return
}
} }
return return
} }

View File

@ -153,11 +153,25 @@ func (this *SCompGateRoute) ReceiveMsg(ctx context.Context, args *pb.AgentMessag
data, _ := anypb.New(errdata.(proto.Message)) data, _ := anypb.New(errdata.(proto.Message))
reply.ErrorData = data 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 { } else {
reply.Reply = session.Polls() reply.Reply = session.Polls()
if this.options.Debug { 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 { //未找到消息处理函数 } else { //未找到消息处理函数

37
services/service_test.go Normal file
View 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()
}