From a76358a89e4448a177e39ec248a64afb8b7ed0a9 Mon Sep 17 00:00:00 2001 From: gy <997485446@qq.com> Date: Sun, 13 Aug 2023 11:55:20 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=95=86=E5=9F=8E=E6=BC=94=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 43 ++++ go.sum | 167 ++++++++++++ main.go | 16 ++ pkg/controller/base.go | 33 +++ pkg/controller/front/product.go | 411 ++++++++++++++++++++++++++++++ pkg/controller/product_backend.go | 173 +++++++++++++ pkg/model/init.go | 63 +++++ pkg/model/product.go | 20 ++ pkg/redistab/redis.go | 20 ++ pkg/redistab/redis_key.go | 30 +++ pkg/router/router.go | 60 +++++ 11 files changed, 1036 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 pkg/controller/base.go create mode 100644 pkg/controller/front/product.go create mode 100644 pkg/controller/product_backend.go create mode 100644 pkg/model/init.go create mode 100644 pkg/model/product.go create mode 100644 pkg/redistab/redis.go create mode 100644 pkg/redistab/redis_key.go create mode 100644 pkg/router/router.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..96fc7cc --- /dev/null +++ b/go.mod @@ -0,0 +1,43 @@ +module worktest + +go 1.18 + +require ( + github.com/gin-gonic/gin v1.9.1 + github.com/go-redis/redis v6.15.9+incompatible + gorm.io/driver/mysql v1.5.1 + gorm.io/gorm v1.25.3 +) + +require ( + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/gomega v1.27.10 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4b47a4b --- /dev/null +++ b/go.sum @@ -0,0 +1,167 @@ +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= +gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.3 h1:zi4rHZj1anhZS2EuEODMhDisGy+Daq9jtPrNGgbQYD8= +gorm.io/gorm v1.25.3/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/main.go b/main.go new file mode 100644 index 0000000..fa7add8 --- /dev/null +++ b/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/gin-gonic/gin" + router2 "worktest/pkg/router" +) + +func main() { + router := gin.Default() + router2.RegisterRoute(router) + + + router.Run(":8000") +} + + diff --git a/pkg/controller/base.go b/pkg/controller/base.go new file mode 100644 index 0000000..c8d3bc5 --- /dev/null +++ b/pkg/controller/base.go @@ -0,0 +1,33 @@ +package controller + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +/** + * 成功时返回 + */ +func Success(c *gin.Context, data interface{}) { + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "ok", + "request_uri": c.Request.URL.Path, + "data": data, + }) + c.Abort() +} + +/** + * 失败时返回 + */ +func Error(c *gin.Context, msg string) { + + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": msg, + "request_uri": c.Request.URL.Path, + "data": make(map[string]string), + }) + c.Abort() +} diff --git a/pkg/controller/front/product.go b/pkg/controller/front/product.go new file mode 100644 index 0000000..b67b0c0 --- /dev/null +++ b/pkg/controller/front/product.go @@ -0,0 +1,411 @@ +package front + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "github.com/go-redis/redis" + "gorm.io/gorm" + "sync" + "worktest/pkg/controller" + "worktest/pkg/model" + "worktest/pkg/redistab" +) + +type ListReq struct { + Title string `json:"'title'"` + UserId uint `json:"'userId'"` +} + +type DetailReq struct { + ID uint + UserId uint `json:"'userId'"` +} + +var synMysqlToRedisLock sync.RWMutex + +func MysqlList(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + fmt.Println("2--------", redistab.RedisClient) + + controller.Success(c, list) + + return + +} + +func RedisBuy(c *gin.Context) { + var req DetailReq + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + + err := model.DB.Transaction(func(tx *gorm.DB) error { + var obj *model.Product + if err := model.DB.Model(&model.Product{}).First(&obj, req.ID).Error; err != nil { + return err + } + + if obj.StockSize <= 0 { + return errors.New("库存不足") + } + + //生成订单 + productOrder := &model.ProductOrder{ + ProductID: req.ID, + UserId: req.UserId, + } + if err := model.DB.Model(&model.ProductOrder{}).Create(&productOrder).Error; err != nil { + return err + } + + //扣除库存 + model.DB.Model(&model.Product{}).Where(&model.Product{ID: req.ID}).UpdateColumn("stock_size", gorm.Expr("stock_size - 1")) + + return nil + }) + + if err != nil { + controller.Error(c, err.Error()) + return + + } + + fmt.Println("2--------", redistab.RedisClient) + + controller.Success(c, list) + + return + +} + +func MysqlBuy(c *gin.Context) { + var req DetailReq + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + + err := model.DB.Transaction(func(tx *gorm.DB) error { + var obj *model.Product + if err := model.DB.Model(&model.Product{}).First(&obj, req.ID).Error; err != nil { + return err + } + + if obj.StockSize <= 0 { + return errors.New("库存不足") + } + + //生成订单 + productOrder := &model.ProductOrder{ + ProductID: req.ID, + UserId: req.UserId, + } + if err := model.DB.Model(&model.ProductOrder{}).Create(&productOrder).Error; err != nil { + return err + } + + //扣除库存 + model.DB.Model(&model.Product{}).Where(&model.Product{ID: req.ID}).UpdateColumn("stock_size", gorm.Expr("stock_size - 1")) + + return nil + }) + + if err != nil { + controller.Error(c, err.Error()) + return + + } + + fmt.Println("2--------", redistab.RedisClient) + + controller.Success(c, list) + + return + +} + +func RedisList(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + fmt.Println("2--------", redistab.RedisClient) + + controller.Success(c, list) + //统计人获取的次数 + return +} + +func MysqlDetail(c *gin.Context) { + var req DetailReq + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + var productObj *model.Product + if err := model.DB.Model(&model.Product{}).First(&productObj, req.ID).Error; err != nil { + controller.Error(c, err.Error()) + return + } + + controller.Success(c, productObj) + return +} + +func RedisDetail(c *gin.Context) { + var productObj *model.Product + var req DetailReq + + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + v, err := redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + + //无缓存 则去mysql同步数据 + if err != nil { + var tempObj *model.Product + if err := model.DB.Model(&model.Product{}).First(&tempObj, req.ID).Error; err != nil { + controller.Error(c, err.Error()) + return + } + + b, err := json.Marshal(tempObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, err = redistab.RedisClient.Set(redistab.GetProductDetail(req.ID), string(b), 0).Result() + fmt.Println("1---------", v, err) + + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, _ = redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + } + + err = json.Unmarshal([]byte(v), &productObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + controller.Success(c, productObj) + return +} + +func RedisDetailLock(c *gin.Context) { + var productObj *model.Product + var req DetailReq + + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + v, err := redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + + //无缓存 则去mysql同步数据 + if err != nil { + synMysqlToRedisLock.Lock() + defer synMysqlToRedisLock.Lock() + + var tempObj *model.Product + if err := model.DB.Model(&model.Product{}).First(&tempObj, req.ID).Error; err != nil { + controller.Error(c, err.Error()) + return + } + + b, err := json.Marshal(tempObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, err = redistab.RedisClient.Set(redistab.GetProductDetail(req.ID), string(b), 0).Result() + fmt.Println("1---------", v, err) + + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, _ = redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + } + + err = json.Unmarshal([]byte(v), &productObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + controller.Success(c, productObj) + return +} + +func RedisDetailBitMap(c *gin.Context) { + var productObj *model.Product + var req DetailReq + + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + v, err := redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + + //bitmap + bit, err := redistab.RedisClient.GetBit(redistab.GetProductBitMap(), int64(req.ID)).Result() + + fmt.Println("2----------", bit, err) + if bit == 0 { //不存在 + controller.Error(c, "非法数据") + return + } + + //无缓存 则去mysql同步数据 + if err != nil { + synMysqlToRedisLock.Lock() + defer synMysqlToRedisLock.Lock() + + var tempObj *model.Product + if err := model.DB.Model(&model.Product{}).First(&tempObj, req.ID).Error; err != nil { + controller.Error(c, err.Error()) + return + } + + b, err := json.Marshal(tempObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, err = redistab.RedisClient.Set(redistab.GetProductDetail(req.ID), string(b), 0).Result() + fmt.Println("1---------", v, err) + + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, _ = redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + } + + err = json.Unmarshal([]byte(v), &productObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + //增加统计,增加去重统计 该商品的DAU + _, _ = redistab.RedisClient.PFAdd(redistab.GetProductDetailLogCount(req.ID)).Result() + + controller.Success(c, productObj) + return +} + +func RedisCountProduct(c *gin.Context) { + var req DetailReq + + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + //增加统计,增加去重统计 该商品的DAU + _ = &redis.BitCount{ + Start: 1, + End: 1, + } + + b, _ := redistab.RedisClient.BitCount(redistab.GetProductBitMap(), nil).Result() + + controller.Success(c, b) + return +} + +func RedisDetailBitMapCount(c *gin.Context) { + var productObj *model.Product + var req DetailReq + + if err := c.ShouldBind(&req); err != nil { + controller.Error(c, err.Error()) + return + } + + v, err := redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + + //bitmap + bit, err := redistab.RedisClient.GetBit(redistab.GetProductBitMap(), int64(req.ID)).Result() + + fmt.Println("2----------", bit, err) + if bit == 0 { //不存在 + controller.Error(c, "非法数据") + return + } + + //无缓存 则去mysql同步数据 + if err != nil { + synMysqlToRedisLock.Lock() + defer synMysqlToRedisLock.Lock() + + var tempObj *model.Product + if err := model.DB.Model(&model.Product{}).First(&tempObj, req.ID).Error; err != nil { + controller.Error(c, err.Error()) + return + } + + b, err := json.Marshal(tempObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, err = redistab.RedisClient.Set(redistab.GetProductDetail(req.ID), string(b), 0).Result() + fmt.Println("1---------", v, err) + + if err != nil { + controller.Error(c, err.Error()) + return + } + + v, _ = redistab.RedisClient.Get(redistab.GetProductDetail(req.ID)).Result() + } + + err = json.Unmarshal([]byte(v), &productObj) + if err != nil { + controller.Error(c, err.Error()) + return + } + + //增加统计,增加去重统计 该商品的DAU + _, _ = redistab.RedisClient.PFAdd(redistab.GetProductDetailLogCount(req.ID)).Result() + + controller.Success(c, productObj) + return +} diff --git a/pkg/controller/product_backend.go b/pkg/controller/product_backend.go new file mode 100644 index 0000000..b2eb96a --- /dev/null +++ b/pkg/controller/product_backend.go @@ -0,0 +1,173 @@ +package controller + +import ( + "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "strconv" + "worktest/pkg/model" + "worktest/pkg/redistab" +) + +type ListReq struct { + Title string `json:"'title'"` +} + +type ProductReq struct { + ID uint `json:"autoincr"` +} + +//RemoveCache 清除所有redis1缓存 +func RemoveCache(c *gin.Context) { + var req ProductReq + if err := c.ShouldBind(&req); err != nil { + Error(c, err.Error()) + return + } + + v, err := redistab.RedisClient.Del(redistab.GetProductOrderList(req.ID)).Result() + fmt.Println("1---------", v, err) + v, err = redistab.RedisClient.Del(redistab.GetProductSaleNum(req.ID)).Result() + fmt.Println("1---------", v, err) + + v, err = redistab.RedisClient.Del(redistab.GetProductStockSize(req.ID)).Result() + fmt.Println("1---------", v, err) + + Success(c, nil) + + return +} + +//RemoveAllCache 清除所有redis1缓存 +func RemoveAllCache(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + fmt.Println("2--------", redistab.RedisClient) + + for _, t := range list { + //销量 + v, err := redistab.RedisClient.Del(redistab.GetProductOrderList(t.ID)).Result() + fmt.Println("1---------", v, err) + v, err = redistab.RedisClient.Del(redistab.GetProductSaleNum(t.ID)).Result() + fmt.Println("1---------", v, err) + + v, err = redistab.RedisClient.Del(redistab.GetProductStockSize(t.ID)).Result() + fmt.Println("1---------", v, err) + } + + Success(c, nil) + + return +} + +func List(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + fmt.Println("2--------", redistab.RedisClient) + + for i, t := range list { + fmt.Println("30----", redistab.GetProductOrderList(t.ID)) + //销量 + v, err := redistab.RedisClient.Get(redistab.GetProductOrderList(t.ID)).Result() + fmt.Println("1---------", v, err) + + if err == nil && v != "" { + u64, err := strconv.ParseUint(v, 10, 32) + if err != nil { + list[i].OrderNum = u64 + } + } + + v, err = redistab.RedisClient.Get(redistab.GetProductSaleNum(t.ID)).Result() + fmt.Println("1---------", v, err) + + if err == nil && v != "" { + u64, err := strconv.ParseUint(v, 10, 32) + if err != nil { + list[i].SalesVolume = u64 + } + } + + v, err = redistab.RedisClient.Get(redistab.GetProductStockSize(t.ID)).Result() + fmt.Println("1---------", v, err) + + if err == nil && v != "" { + u64, err := strconv.ParseUint(v, 10, 32) + if err != nil { + list[i].NowStockSize = u64 + } + } + + b, err := redistab.RedisClient.PFCount(redistab.GetProductStockSize(t.ID)).Result() + fmt.Println("1---------", b, err) + + if err == nil && v != "" { + list[i].Uv = uint(b) + } + + } + + Success(c, list) + + return +} + +//Clear 清除数据 +func Clear(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + + Success(c, list) + + return +} + +//SynCache 同步redis +func SynCache(c *gin.Context) { + var req ListReq + if err := c.ShouldBind(&req); err != nil { + Error(c, err.Error()) + return + } + + var list []*model.Product + model.DB.Model(&model.Product{}).Find(&list) + fmt.Println("2--------", redistab.RedisClient) + + for _, t := range list { + v, err := redistab.RedisClient.Set(redistab.GetProductStockSize(t.ID), t.StockSize, 0).Result() + fmt.Println("1---------", v, err) + temp, err := json.Marshal(t) + + v, err = redistab.RedisClient.Set(redistab.GetProductDetail(t.ID), string(temp), 0).Result() + fmt.Println("1---------", v, err) + + //同步bitmap + redistab.RedisClient.Del(redistab.GetProductBitMap(), string(temp)) + b, err := redistab.RedisClient.SetBit(redistab.GetProductBitMap(), int64(t.ID), 1).Result() + fmt.Println("1---------", b, err) + + } + + Success(c, list) + + return +} diff --git a/pkg/model/init.go b/pkg/model/init.go new file mode 100644 index 0000000..e8c740b --- /dev/null +++ b/pkg/model/init.go @@ -0,0 +1,63 @@ +package model + +import ( + "fmt" + "strings" + "time" + + "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" +) + +var DB *gorm.DB + +var ( + DbUser string + DbName string +) + +func init() { + //MySQL数据库 + DbName = "shop" + DbUser = "root" + path := strings.Join([]string{DbUser, ":", "123456", "@tcp(", "127.0.0.1", ":", "3306", ")/", DbName, "?charset=utf8&parseTime=true&loc=Local"}, "") + //连接数据库 + Database(path) +} + + +func Database(conn string) { + var ormLogger logger.Interface + if gin.Mode() == "debug" { + ormLogger = logger.Default.LogMode(logger.Info) + } else { + ormLogger = logger.Default + } + fmt.Println(conn) + + db, err := gorm.Open(mysql.New(mysql.Config{ + DSN: conn, // DSN data source name + DefaultStringSize: 256, // string 类型字段的默认长度 + DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持 + DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引 + DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 + SkipInitializeWithVersion: false, // 根据版本自动配置 + }), &gorm.Config{ + Logger: ormLogger, + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + }) + if err != nil { + panic(err) + } + sqlDB, _ := db.DB() + sqlDB.SetMaxIdleConns(20) //设置连接池,空闲 + sqlDB.SetMaxOpenConns(100) //打开 + sqlDB.SetConnMaxLifetime(time.Second * 30) + DB = db + //migration() //迁移表 +} diff --git a/pkg/model/product.go b/pkg/model/product.go new file mode 100644 index 0000000..ed64773 --- /dev/null +++ b/pkg/model/product.go @@ -0,0 +1,20 @@ +package model + +// Product +type Product struct { + ID uint `gorm:"primarykey"` + Title string `gorm:"column:title" json:"title"` + Introduction string `gorm:"column:introduction" json:"introduction"` + StockSize uint64 `gorm:"column:stock_size" json:"stockSize"` + SalesVolume uint64 `json:"salesVolume"` + OrderNum uint64 `json:"orderNum"` + NowStockSize uint64 `json:"nowStockSize"` + Uv uint `json:"uv"` +} + +// ProductOrder +type ProductOrder struct { + ID uint `gorm:"primarykey"` + ProductID uint `gorm:"column:ProductID" json:"ProductID"` + UserId uint `gorm:"column:UserID" json:"UserID"` +} diff --git a/pkg/redistab/redis.go b/pkg/redistab/redis.go new file mode 100644 index 0000000..2f5bc2c --- /dev/null +++ b/pkg/redistab/redis.go @@ -0,0 +1,20 @@ +package redistab + +import "github.com/go-redis/redis" + +var RedisClient *redis.Client + +func init() { + RedisClient = redis.NewClient(&redis.Options{ + Addr: "127.0.0.1:6379", + Password: "", + PoolSize: 20, + DB: 1, + }) + // 检测 + _, err := RedisClient.Ping().Result() + if err != nil { + panic(err) + return + } +} diff --git a/pkg/redistab/redis_key.go b/pkg/redistab/redis_key.go new file mode 100644 index 0000000..4644cfb --- /dev/null +++ b/pkg/redistab/redis_key.go @@ -0,0 +1,30 @@ +package redistab + +import "fmt" + +//订单 +func GetProductOrderList(productId uint) string { + return fmt.Sprintf("product:Order:%d", productId) +} + +//已售数量 +func GetProductSaleNum(productId uint) string { + return fmt.Sprintf("product:Sale:%d", productId) +} + +//库存 +func GetProductStockSize(productId uint) string { + return fmt.Sprintf("product:stock:%d", productId) +} + +func GetProductDetail(productId uint) string { + return fmt.Sprintf("product:detail:%d", productId) +} + +func GetProductBitMap() string { + return fmt.Sprintf("product:bitmap") +} + +func GetProductDetailLogCount(productId uint) string { + return fmt.Sprintf("product:log_count:%d", productId) +} diff --git a/pkg/router/router.go b/pkg/router/router.go new file mode 100644 index 0000000..b50c4ab --- /dev/null +++ b/pkg/router/router.go @@ -0,0 +1,60 @@ +package router + +import ( + "github.com/gin-gonic/gin" + "worktest/pkg/controller" + "worktest/pkg/controller/front" +) + +//api路由配置 +func RegisterRoute(router *gin.Engine) { + //middleware: 服务错误处理 => 生成请求id => access log + + //api版本 + v1 := router.Group("/api") + { + backend := v1.Group("/backend") + backend.POST("list", controller.List) + backend.POST("all/cache/remove", controller.RemoveAllCache) + backend.POST("cache/remove", controller.RemoveCache) + backend.POST("syn/cache", controller.SynCache) + } + + { + backend := v1.Group("/front") + backend.POST("mysql/list", front.MysqlList) //数据库连接 + backend.POST("redis/list", front.RedisList) //缓存连接 string/hash + backend.POST("redis/", controller.List) //缓存 + backend.POST("getlist", controller.List) //mysql + + // jemter 对比 + backend.POST("mysql/detail", front.MysqlDetail) //数据库连接 + backend.POST("redis/detail", front.RedisDetail) //redis单商品详情 无锁保护 可缓存击穿 + backend.POST("redis/lock/detail", front.RedisDetailLock) //redis单商品详情 有锁保护 可缓存击穿 + backend.POST("redis/bitmap/detail", front.RedisDetailBitMap) //redis单商品详情 锁保护 bitmap缓存击穿保护 + backend.POST("redis/bitmapcount/detail", front.RedisDetailBitMapCount) //redis单商品详情 锁保护 bitmap缓存击穿保护 增加访问统计 + + //增加bitmap的统计等 + backend.POST("redis/bitmapcount/productcount", front.RedisCountProduct) //redis单商品详情 锁保护 bitmap缓存击穿保护 增加访问统计 + + backend.POST("mysql/buy", front.MysqlBuy) //抢购 mysql事务 + backend.POST("redis/tx/buy", front.RedisBuy) //redistab 事务抢购 watch unwatch mutile exec + backend.POST("redis/lock/buy", controller.List) //redistab 分布式锁抢购 setNx lua + backend.POST("gortout/buy", controller.List) //go语言锁抢购,协程模拟锁 + backend.POST("getlist", controller.List) //go语言锁抢购 + + /* + + backend.POST("getlist", controller.List) //推荐列表 list + backend.POST("getlist", controller.List) //推荐去除已买连接 set/zset + + //jemter对比 + backend.POST("getlist", controller.List) //websocket redistab 广播 receive + backend.POST("getlist", controller.List) //websocket redistab 广播 chain + backend.POST("getlist", controller.List) //websocket go通信 协程通信 + + */ + + } + +}