From ccd2c530cf58c1e7f1aa145a631a6d595ee456fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=9A=AE=E8=9B=8B13361098506?= <718964169@qq.com>
Date: Mon, 6 Jan 2025 16:21:36 +0800
Subject: [PATCH] Apply .gitignore rules
---
.idea/goProject.iml | 9 +
.idea/modules.xml | 8 +
.idea/workspace.xml | 49 +
.svn/entries | 1 +
.svn/format | 1 +
...cf129372b636ccad5355eca7cd5992f37.svn-base | 34 +
...16eefcbc7222fcf148fae2d4a027038d1.svn-base | 110 +
...76a09918ae8e11a6ea4ea0baebb972248.svn-base | 29 +
...9b44c6f1155fa6d3b8d81d7557fdea2a1.svn-base | 129 +
...1ec8c3741fb44e0c141d45af65b1dcf19.svn-base | 36 +
...9030f7fb4c2de649a85be0862d57334ba.svn-base | 658 ++++
...a6bc1d05c1f484952a04efc5e992d3c89.svn-base | 73 +
...d74eace2e9a84bcbe81bc0966d9a44600.svn-base | 35 +
...feee3f43be99fed3c1fd0412e261ae3a5.svn-base | 88 +
...5ed351569e457445896fd1913ce46d45b.svn-base | 98 +
...c69165cb7077f9e740559446368aca1f2.svn-base | 78 +
...8fbce45201919045075139dc8513be286.svn-base | 67 +
...017ca5d27710d505ac314376753225cfc.svn-base | 25 +
...7beadc6d8dace22ef80979ab50388eeea.svn-base | 38 +
...4d0991e86509f1059a6f59d487d6eadbf.svn-base | 259 ++
...e62906601a10b242b5729b54e02e6890c.svn-base | 19 +
...6d970c791745423200210d5c8eced9132.svn-base | 80 +
...460cfe541898e77c9fb5904023dcd9457.svn-base | 14 +
...62368c2b1dc512b9b3abd7951d62168e5.svn-base | 13 +
...d97d7dc9708f61a91bdf317d06b7b7d83.svn-base | 18 +
...e789e52c6207035406c7a797712e93165.svn-base | 265 ++
...515939483a29f46f368d7bd7db0165b49.svn-base | 73 +
...adf4e5244aa44094b27c6e4e39d8a1f2d.svn-base | 39 +
...b9b9471a4ea96b66c1cc364911ab54b99.svn-base | 55 +
...46a4b445d18be34fff4f29b1e4b180b35.svn-base | 41 +
...f9322e065863083d01d249ef44cf69dc5.svn-base | 4 +
...2d48171632e253b32b808a1222c5e7681.svn-base | 33 +
...d02242d905fb9068a5756c87c3a5aa2fe.svn-base | 7 +
...389b0629d492c0cc4dab91d9b280686d2.svn-base | 44 +
...94a211ca755865be522ee4fc139d7b3f1.svn-base | 19 +
...d1add98c087081650bab4b1dc4ba8424b.svn-base | 41 +
...b2c63205e8f54bb6bb60b43880f54c4a8.svn-base | 43 +
...54b3ab7b1fa88a882ac9120820be781d1.svn-base | 6 +
...98f1552816faf3d86834fb1b66bf8bf50.svn-base | 155 +
...79a2d82d7163bf69aa24a408f279cd51a.svn-base | 64 +
...80db1cb87c67f3c144daf44fb3b086161.svn-base | 86 +
...356a1fb59be2104ee2e958491fa209bf6.svn-base | 17 +
...68a7edc2b57740acf0aacde3feac27ecc.svn-base | 114 +
...abad97f3332dd60150062cf10fd36945d.svn-base | 8 +
...23727057f2372bcb30ec7552664b06138.svn-base | 141 +
...39f7d2565fa8e1274fd45c809c65da569.svn-base | 330 ++
...e30c7ac55d6efe3eaf1f188a4151a7571.svn-base | 206 +
...238f6e4771bc74430cc3f2bee6b274238.svn-base | 109 +
...943ccae37879b6dbde2815a17b6504038.svn-base | 61 +
...45ee771a7b2811130a3b416d486e6e892.svn-base | 71 +
...70913bfc03a551aa87944abac426b9072.svn-base | 13 +
...0c04874ab483587453f0e175feeb4c956.svn-base | 105 +
...bec35d99e08a5f0ff52f0c36225adff02.svn-base | 54 +
...3f1013e25716d622f56b3972e13598eea.svn-base | 89 +
...edb1ebc33483b575fba2f0df647af9e8a.svn-base | 20 +
...72d7c0e0fdc2fe718e7d1e71f371e8ac6.svn-base | 76 +
...f1959026fcd250504d7000e59f58e3b41.svn-base | 53 +
...74c1cb8cdd4b7ad9f7efe545734fe2675.svn-base | 127 +
...3d729f98b5b8564f2033328f4aee93dc0.svn-base | 76 +
...b5dae47034a6e1eca1f65ebcdd985ab61.svn-base | 80 +
...d8c4ec0d0b345954e5fcd054c655fcda7.svn-base | 15 +
...5ee184352bf16c2e23e049560a9b6ba80.svn-base | 93 +
...a2a253139cdd05cf26644b4f525c60e99.svn-base | 210 +
...5fb3a29c19e78e2e5e1e308e4bc2551c4.svn-base | 73 +
...e98b05475fc80c58a3255322d410a1a84.svn-base | 68 +
...cc246b38d375d7d7cf3d46f677afc9de1.svn-base | 2 +
...67349e079d14ba9d6e284cd8a2cbd2ca4.svn-base | 1501 +++++++
...be2fbc6102cfdbb3d5e7b672995ea4226.svn-base | 114 +
...9abfb9fb4344aeefa35ceadca73f1fe4c.svn-base | 587 +++
...3dbc796a3f5f0281152a47b2d363859d6.svn-base | 54 +
...b7678eef959ff8f8c0e69d4051e45ed17.svn-base | 83 +
...dc10711a9b500c6dea251529f59d249f0.svn-base | 35 +
...f707f332983e7042674e7c933e71d089e.svn-base | 40 +
...07433453f47a849b07a75501b86ac53eb.svn-base | 36 +
...5a847601c48c478898d552ab339455646.svn-base | 6 +
...22548d93244351bbac432d4a7cdde9667.svn-base | 22 +
...80bd20fd584e9675d554ea02cb7d35caa.svn-base | 377 ++
...06a95554c30263afa7ce43d3775f1dcdb.svn-base | 34 +
...881b113926160df0087f10a47ea9e87ff.svn-base | 62 +
...99036df716050665854c27a1925523227.svn-base | 137 +
...3e36d220fc9a9e9944b67bc4d96bd8d26.svn-base | 20 +
...07677509afe5a28cf69b7241d9675e0c1.svn-base | 82 +
...0bea424ffed61b3775e9a3885c7c78fac.svn-base | 219 ++
...834766c7d74d55dbfaf1b49771fd9e489.svn-base | 54 +
...abd801627575e7862f59be14761f21a15.svn-base | 123 +
...a6504067877bec738054b2ee97658da3d.svn-base | 16 +
...bd48538f9d2f8b36722a664b308762e83.svn-base | 16 +
...4e39cd278edd81f86a6b942d541ea2921.svn-base | 133 +
...d2e72184a45660ed9c67c714a06107c62.svn-base | 109 +
...d5a16af36ce250d440564fc2b747e6dd4.svn-base | 79 +
...907392c148b50ae48efa6d7f9e9746822.svn-base | 225 ++
...66dd2f7a93da426d59d796617815b5714.svn-base | 1575 ++++++++
...c8aada772e1f6465d18604e289c9e5489.svn-base | 378 ++
...e9e9fd164ec610c7921a8639c1dcbfb15.svn-base | 131 +
...a11741f20169313a7438cfe711b0ee295.svn-base | 112 +
...98a6ac756be9f2d95dd9e284ddb2338b4.svn-base | 17 +
...72b6314d517f3a9c48c61c54f3b4d315d.svn-base | 8 +
...a04ade2aafd862fcba87d65aa33d2dfa4.svn-base | 130 +
...975dbbbc57bf60a2d6c23dd8242dce9b2.svn-base | 57 +
...336934c29f0bf81f0e3cfb3ba03e237b0.svn-base | 6 +
...11847c786465856bc05af9651a484188c.svn-base | 71 +
...2b9e8a852f03d50095156e421917e10b3.svn-base | 75 +
...6fe53177181f083b4ac4b0cd9fba5b1fe.svn-base | 18 +
...905747f4fa5f73ac48126d3788f20ea2b.svn-base | 343 ++
...47a58e684f5d5c35587c678482c56dc2d.svn-base | 32 +
...565a8992159b26fd4bcb62dd98d3f8e35.svn-base | 14 +
...76f1f72118d5726c9a45ee3c678037629.svn-base | 295 ++
...2647fe7e9eb22c3f13cd5afd8135b0dab.svn-base | 91 +
...a7794d3b03ba2af46e7a5709253508107.svn-base | 78 +
...a0fa2a5a57e9f7e655eb3d363f14c41be.svn-base | 6 +
...ba27e67d1efdfc163a25f3b7bd611f8a6.svn-base | 57 +
...65bcd2cea0e001934e67db11e0fea1405.svn-base | 78 +
...5919f4eac85c32fd101e5bd303ef1190c.svn-base | 4 +
...c21083bfc1741db5df016b198b53ae6ad.svn-base | 8 +
...88af8b1eec3c306160021488411784adb.svn-base | 54 +
...a9c1257d723c197f604ecb9c540c228fd.svn-base | 313 ++
...b60fa320c31dece98ac92ee259e9a5f3e.svn-base | 40 +
...53c528a2ecc3d58647e3be3906413ea67.svn-base | 135 +
...878ea7aff20885d6b00cc935dbd706a3e.svn-base | 15 +
...4f4755f5db8d0594c2929c51ee463b213.svn-base | 84 +
...aef962809ed3ade0ffa38bd43ad47b521.svn-base | 131 +
...5bd4317d500dc2743379a8be288c087a9.svn-base | 204 +
...a52e20e4a543ae33d5269808f02e5b7e4.svn-base | 101 +
...982390c2ec9a716fcddcea8bc20697680.svn-base | 183 +
...f92484c30f0522d74cc475fcffe1f82f7.svn-base | 142 +
...d0646acce265d7166cd02d78a6807aea2.svn-base | 12 +
...ef28dd736d756c6d320e069c3ab89f068.svn-base | 53 +
...d1781aebf4bed60ed3aadb529219c3f32.svn-base | 131 +
...d458ab13b56f9ac7761adf383671377ed.svn-base | 67 +
...b7da2660d83da36bd4e0b728e917c7f96.svn-base | 231 ++
...e93e1d7fb867c6043db15d57863b64727.svn-base | 47 +
...c1e01175f811d01e6be3886accfb3919f.svn-base | 8 +
...ad7e807c519e9f84e8e45315bcb11bee2.svn-base | 63 +
...849a9eca9f553cedecc4a9b2ebd621b23.svn-base | 36 +
...8770e13e0ad7e76c3c6635a87600816b2.svn-base | 83 +
...6c7541bc544702d797fcbda5918ed0177.svn-base | 57 +
...601698339d1c23760a5460bde5c1412b5.svn-base | 221 ++
...7eafa0d8f7a60cec4a9b30a2133bcc6bb.svn-base | 409 ++
...6b063ca1786642aa7e12792c0a26d104c.svn-base | 16 +
...e2ee1aaaeff3dcc4e23bb2a1391220586.svn-base | 19 +
...b825adc910983b41ee6e2df86611ca117.svn-base | 193 +
...00c968fc5f809e08ddcf2abcc2774fd2b.svn-base | 186 +
...1543987b2fc1e5ad1e0041ffbbef1231f.svn-base | 6 +
...7cff7c5629f6a5f38855e9ad2891bca8e.svn-base | 208 +
...c232c02a13b29a2b8ea947d48e87e0798.svn-base | 54 +
...5c664eb83dc8772b69254ad4263c18541.svn-base | 259 ++
...5683add574e0b3b1b5c7e521de4a47ad3.svn-base | 100 +
...2166c4d38707ec9cc9c910dd1e4ff2dd8.svn-base | 267 ++
...187ec9411b0df5744d9cd02879fa239f4.svn-base | 88 +
...814b5fbe104eac0a7b7d76bf8dd007800.svn-base | 56 +
...a3836e96a64416fbbd2ebafdebd1fc2ab.svn-base | 46 +
...3da7294f5fed68348b9d711e4e403aeb2.svn-base | Bin 0 -> 5985 bytes
...f3b3e887131b06e7b527762a83a3c41db.svn-base | 24 +
...e5ebd4d12dbdf32a30bfb9bd84a970159.svn-base | 95 +
...0b7a243190727cdff70cde0a7dcf33931.svn-base | 378 ++
...73450f16557c41cc40bc68d5bca11839e.svn-base | 109 +
...7237af34809acbd8293feabe883b1d689.svn-base | 37 +
...fd695edc9cc00309e90205cafdb4ea415.svn-base | 233 ++
...17638beef3ca372b2de090fd58b2e17d7.svn-base | 16 +
...fb77af67f2f9564918a01fa309f8f6815.svn-base | 52 +
...42f5c5969f7878c2074d3b3ebe0f9c003.svn-base | 450 +++
...1186639ab7ed02dd5ccd2c781cf61b193.svn-base | 46 +
...33451632d39ca579614e8ddfbf9781d0f.svn-base | 70 +
...137557b0aa604619fa267109dfadd8834.svn-base | 95 +
...1515a55d48e5d25081f9210b9da4ff66c.svn-base | 35 +
...3b8c1a3af9e234f21ac76c082a4f9ff7b.svn-base | 33 +
...fdc1b824c9dcb29ac73ba4313e7b94906.svn-base | 47 +
...7a56519f9549a2f2f3f364207e68b78bb.svn-base | 98 +
...78217ea55998820ec3ca6c0e9ae15c4f0.svn-base | 3 +
...84756d5cf8e2dd0c2ef3ccb48f3739826.svn-base | 103 +
...3370b259aefd77d242d38fd7769811a8d.svn-base | 102 +
...ab2a9efeb7b70840597892f85147de079.svn-base | 208 +
...c59968de8708cb631ec180d949e04a2d8.svn-base | 186 +
...3b9bd0b80cd60485a6013941777b27d7f.svn-base | 47 +
...bc4c52b9546cd5900c63f09387213c2e5.svn-base | 166 +
...3a26885328f556159b055b3d369732600.svn-base | 16 +
...a37d3cf0affa5dd7f1a866f5375ac5629.svn-base | 71 +
...d36b3f0c082e6782f864014eb4e07d2a5.svn-base | 1733 ++++++++
...a1a6493e340cfad0e3092a40126a4aece.svn-base | 43 +
...721098eea260b5d302d760e536bb7e64a.svn-base | 35 +
...4731af6df40aa03de3ed2ecdba22db264.svn-base | 135 +
...ca5ea1ebef8ef05e1ac43f034ae2cc57a.svn-base | 4 +
...3aaa4f5248637d444f7ab2c0fef970cc8.svn-base | 216 +
...9e7af5f1f82645c1b1302f1536f95c33f.svn-base | 225 ++
...4ea3bdc4d3c6456f7cd29c29cd7bd701d.svn-base | 58 +
...b02485de6eb3a2c938963067ee4ef19bf.svn-base | 7 +
...6c29cff02591a87a5b23b6d636baf73e0.svn-base | 126 +
...51d4b9f74fdb2c8830143bbaec17f3ce3.svn-base | 167 +
...3d261e7448019224293b8c2f300ee0ab3.svn-base | 27 +
...4a6d4b535e3554239a36e580922efb062.svn-base | 77 +
...56ca8b6b4c1684486b413f058cbcdef5b.svn-base | 18 +
...b45d8fe9611097a5640452068f52cfc06.svn-base | 208 +
...1719fe7c5227e762a9cfdbfea79af5c81.svn-base | 37 +
...5915e4e0a382656f419b23ec37c1dea9a.svn-base | 77 +
...0a024b2d740a38545632f8b07a313f9ec.svn-base | 182 +
...f8b846194d5b8e73a078da71adaae6dfd.svn-base | 4 +
...1a62c7b4795266420a89faf8955b3a29c.svn-base | 13 +
...81285493617e456ee5193122cba2fe3e3.svn-base | 186 +
...a989f3a71d3af9af1cc1514017f4c3b2d.svn-base | 53 +
...ae7afcad71966e2a8f30ed0f0ee23991f.svn-base | 14 +
...4997979f5889d26f7a025ec34dd3405f1.svn-base | 132 +
...66d28f994d025ce139e3a8e09bfb68196.svn-base | 16 +
...2fd6262e24fa94fe5e10814532f88b5bf.svn-base | 247 ++
...8c997feaac3b622c39ef0886b149d80e8.svn-base | 41 +
...faa37789ec76a10782c878db5e00b7e43.svn-base | 26 +
...62218b6c17d558654dfe26659205489a0.svn-base | 15 +
...29df5269adfb1bb29dba1fb1b34ce16bd.svn-base | 99 +
...d3dd2f5232b9c9c3ca1dcfaed71e2c9bb.svn-base | 91 +
...74bb697f0fe69c523d081a0ef9645d4bf.svn-base | 32 +
...1d094644512c078a85a8cf10b20959f04.svn-base | 81 +
...996c3cd3c94a7b7422b369a6540ad167a.svn-base | 198 +
...24e52f1a9c27470de900d08085d5fc9d1.svn-base | 20 +
...3b6a9a0d075c29e4af206bb73d7e042a4.svn-base | 860 ++++
...9e5532c6fa13a4bdf8e311311407deff0.svn-base | 400 ++
...1ace94d6dc0a08b6752112ec23c9e90ea.svn-base | 82 +
...7e3409c1fc1075865f0d23cd455d28d1f.svn-base | 184 +
...767b223adba34dffed1cabbbbbcb8210a.svn-base | 13 +
...4277f63f045f0d9feff1a77292f1eada0.svn-base | 93 +
...22ee53e31116a0cc59afcda10b566881f.svn-base | 27 +
...77b85e4e36232243c7273ed32a23df5dc.svn-base | 120 +
...48d38e77bea09228526e4a1cc66a86fd9.svn-base | 175 +
...ff47876b2475132ee02919a860a69a8d5.svn-base | 19 +
...351dc932639f48484b5f38da44c769cab.svn-base | 70 +
...1bf55a499ca0575b8b4af358bbfbb7565.svn-base | 131 +
...1bf41c73ac8d2169614eb70b18e7551ae.svn-base | 56 +
...1c712eed283d8593d10c63d946be7337c.svn-base | 218 ++
...5e01acc3892a93342d49523e7afb43b05.svn-base | 99 +
...71df6614fa95300a808373169e18b0950.svn-base | 87 +
...f6e9be1f84238e9cb97288fda3cb63dd8.svn-base | 345 ++
...fe93f6f0a7f5115c7b8607aed51ee86b3.svn-base | Bin 0 -> 2239542 bytes
...ff77b3c733abee24187f2c857e1575160.svn-base | 394 ++
...03def080514a6099b44ebf7859d676dfa.svn-base | 25 +
...6b4ef4842fdf73cda2293b84c0a1a594e.svn-base | 89 +
...fc80001d9b4fd6ad73d8acf97f1791a12.svn-base | 40 +
...64917cdc9be9a1c4e95d8be9514c251bc.svn-base | 28 +
...157ac917a85023be10ae67e3cb858fc36.svn-base | 84 +
...5c16e41033bcb6a62a5b8f4381c1269d3.svn-base | 10 +
...8049def9bef1529c3cee8e41064f42398.svn-base | 16 +
...cc5e3ebe389ecf298872d498c1627b692.svn-base | 431 ++
...b7a8b435762332e2dca283ce69d621742.svn-base | 33 +
...884776f00b5f5b2567d61c4e002873e42.svn-base | 178 +
...9fd99648487db8e77ab74a256057d05c1.svn-base | 58 +
...69bb8e4a3354541002925d04ae2c67206.svn-base | 38 +
...bbce449bca217b7cf8f47597cb2e80b4c.svn-base | 29 +
...df3a0eef942cb42a5d2edf3b8aeccfa06.svn-base | 3 +
...b01bd32a29ffbb06e7d26923eb9e0b99f.svn-base | 36 +
...901677b3d015a29e4a97842a54bf31b55.svn-base | 315 ++
...2eff7b99141ac4f11df390f8472aed419.svn-base | 25 +
...847706ef76e4ce91b3cb134f7cba7b934.svn-base | 223 ++
...e625c251705202b05c9c86db26f849ce0.svn-base | 61 +
...76c536023aa70a4636340051de98f98f5.svn-base | 32 +
...475bfbd32efc844dcbb6477da14be104b.svn-base | 374 ++
...7e4996aeaff2750f6d1d29937beacf1a9.svn-base | 325 ++
...4db7c164592c699679747f995b2fc8873.svn-base | 37 +
...120b1822c2510bf2b96cddbeba44640e0.svn-base | 63 +
...70c9b2dfadb1781397fce37a2913868a8.svn-base | 329 ++
...99c22899881828e41c73aedf42b01c556.svn-base | 139 +
...bb6de28bf6f10a6acbcec488fec3d1012.svn-base | 44 +
...140910e9ec1132c16f86bcd1b3e49f281.svn-base | 54 +
...9ab9c1af6a6eaa750ecc1a2608741f5c0.svn-base | 43 +
...3514203e0e2ad638d675e7945aa45f504.svn-base | 298 ++
...450d993408705a40f6c4c6f9b73b61e40.svn-base | 69 +
...31596d4ca384380e02a63ef4865b44de0.svn-base | 120 +
...546d91420a0e3443ed43eb1701600c23a.svn-base | 146 +
...36318f52b3e73dbec82adcd0763b6070f.svn-base | 154 +
...3b3f6bf0d01a81cd0dba737f90329d6d8.svn-base | 179 +
...96cd96d125a43029e9404b89170ade3f0.svn-base | 30 +
...7d78433f650b2d900e33537b2850405c6.svn-base | 56 +
...e63a7bb9a2d7ca1de86124879b983ab80.svn-base | 381 ++
...e1d52f692154f322705a6637c1850da7c.svn-base | 108 +
...ff6dc7447697e0e88878aee8545ba6de6.svn-base | 76 +
...dbac37c4407fb1d7c8b8d533f0e3c5db3.svn-base | 40 +
...4c656bce8aa2661657a925bc48f310ade.svn-base | 75 +
...b4427453bd07542db3342d3bac1936571.svn-base | 39 +
...498cfe5ae20b2c4041e07e09b7ca1f8e1.svn-base | 10 +
...5c075f0e6678f5c2b15e3922205cd47ee.svn-base | 54 +
...87c8788dbd8b139458356324e132a4488.svn-base | 316 ++
...99049ecf6af01bcf74ba7a8e5e4e0afb1.svn-base | 30 +
...da0ca1fe6074ad84d3c847f9c7bf63726.svn-base | 31 +
...6d7b36650e2fd6ba7c246c03aa2ba8eee.svn-base | 243 ++
...2879e32df7b13f342446694068da6889d.svn-base | 4 +
...b7e7de819d001cc33ee69fd6adebc0c1f.svn-base | 309 ++
...ee88994ee7787a48be5857cecbb05c19a.svn-base | 420 ++
...b5be5012cb834c3294f238aa09f8ed694.svn-base | 416 ++
...767782273553887125668d1ee84d4f646.svn-base | 4 +
...c171ac5c4b573ca5862f14d15b0b6e1dd.svn-base | 196 +
...9739d0187dc080c10c4a278eb975a9edd.svn-base | 265 ++
...1e23055bcf5224ceccf7375d43fc958d5.svn-base | 58 +
...99a2115c3bd270cbc79c827375577fa95.svn-base | 57 +
...f48dc30040e033e21d4245206e1523445.svn-base | 89 +
...7bbfd5bbdca0eb0004d34288120bea1a8.svn-base | 27 +
...5ce657255545a6a2946a1bce7ff20f8f5.svn-base | 111 +
...91775348234abd80a4f60c40470b0bca0.svn-base | 23 +
...59d643aec9723d14b0032a28ff5ff1ccf.svn-base | 269 ++
...0b24a931070fc286efa8622d2037259d9.svn-base | 48 +
...d7aa4a712f94227106a3f15cfc054926e.svn-base | 82 +
...725105ff9036724f89c5b79c473a903d2.svn-base | 71 +
...2bb482c2353076eae6992fa4742b18f9e.svn-base | 227 ++
...8a02fa42a59d2cdd1e4813287c903ba4b.svn-base | 13 +
...e1f39a71cf768fe2b76b65ec4b3ec66f9.svn-base | 188 +
...200c5e064d0a1548f0e289daadf7ef2b8.svn-base | 14 +
...8ca6f8b3d939693d960919c02ec6f8edd.svn-base | 20 +
...684a8f2323d841b58e5517303a5e2b37d.svn-base | 62 +
...d3f105d0edf6cdeaa093d587b1c9882bf.svn-base | 27 +
...b4f791b928f4c564b112d1ae9f04c464f.svn-base | 46 +
...9082e5a7d4306757bd4233b3e049cbfd2.svn-base | 156 +
...50db01555b35793490e90ba2e09348ad5.svn-base | 251 ++
...272c56a0aeb23f714c0b321ab8d037c66.svn-base | 144 +
...7f9123c25db31aec5a6632fbf28ef03e6.svn-base | 29 +
...a877fe9510bcb348627d52db70ebb70e6.svn-base | 29 +
...ad52170308cdae2c6d5a64950f815cd4e.svn-base | 21 +
...e181ac4dcb2f45d4e70737b702328124d.svn-base | 50 +
...3407a4f43552270d1d03fec78949097a5.svn-base | 104 +
...2ce0b67b6d649e245ea13e17ffba40ab9.svn-base | 63 +
...3b0d60da1f3de24e50d2372552822372f.svn-base | 65 +
...789a7eb735412542d295753784c122a5c.svn-base | 203 +
...cbaa0a1de1cb596d242e34c9a57e36007.svn-base | 158 +
...71d1b10febb41d27c82dfb6fe0aa531aa.svn-base | 60 +
...9c2ddf90e31b713a8b7cc90e8d2b87fe0.svn-base | 1 +
...d90929feaca46d59d98ee748639b617fe.svn-base | 5 +
...e3ed3340138e2d205d61386137a224149.svn-base | 9 +
...d4d20c589b00d8081b602a0a8f645396a.svn-base | 40 +
...d45f3661b72ea781eee839c580872c6ba.svn-base | 15 +
...1144747bd0f94d996b4042ef26f184531.svn-base | 66 +
...16d77465e773ffcf4c4aa1e3d4ed4bf12.svn-base | 3 +
...4544679d71ce893276c3eeef5d398a410.svn-base | 12 +
...fb2155d3e78b896eab7c735e569f0b4af.svn-base | 40 +
...fe356fb9c0954d63499cb8198f3ea2c60.svn-base | 23 +
...e4874ad88b5459c4c59ae26b7d9648f15.svn-base | 60 +
...854daad6cfdf50419e61fd334d0d69988.svn-base | 28 +
...f21697a4fd06ac8def4685ee38fd87c88.svn-base | 11 +
...7f6e594883c5f95343cebb4be7d057a73.svn-base | 15 +
...6a9d3c9170ddd1851e7d4781d8b7091b5.svn-base | 50 +
...bd3ac4b211249bac4ad8fbf11a3173407.svn-base | 64 +
...aae25ace2bc1b2fee3a11dec614a65299.svn-base | 61 +
...6d7e8a79b22b92bebbfdbad4754e0cba2.svn-base | 36 +
...6cddbce2fb52c50f65c2debf471676f59.svn-base | 42 +
...62b62d4cdbe7e7560e0680c941dd3e6f7.svn-base | 16 +
...69d180eab8f04a6d5e672584ff2fc71ee.svn-base | 38 +
...4a07d51f484a829817f9fb230eebd4d2f.svn-base | 104 +
...d9a3b9483b641cf7b63a2cde8c23cc467.svn-base | 1 +
...94ae4f0b517aa97eb54df20067c2a200e.svn-base | 58 +
...264f76d12306f58d53b50a9bde3842980.svn-base | 163 +
...7a2c7cccae9b9407f3dad3177901ed128.svn-base | 13 +
...41186ec3cb94e0f46a53375aaa0a2ac64.svn-base | 113 +
...7c01998cc21b4039aceb05c5357a120a9.svn-base | 73 +
...d7f4671f492f2b411c9c28342621a38d2.svn-base | 82 +
...0faea32304a45a8bcf00535558167ab90.svn-base | 100 +
...3914e684b39e38aaeefb04a3406a33e22.svn-base | 18 +
...6f34f9675d1c724a0bd1275d58cffa242.svn-base | 121 +
...4a97d9779f8bde4b20731baad9dd5059f.svn-base | 114 +
...32db761185cc722e9e153c5bae1349942.svn-base | 11 +
...e06a343fd032c825b9db1a1624e030ce8.svn-base | 45 +
...0740705527e7ced9f8d11475f2e971383.svn-base | 412 ++
...0d51489403a4cac6a96125226175fcc51.svn-base | 20 +
...d53a6967f418cdd5062899fe17a1aea4f.svn-base | Bin 0 -> 9620480 bytes
...b2034911b23a4c9b55d33f68143b0a5f0.svn-base | 28 +
...5da7bf4ff94fe15d1c7a6915f9430cf80.svn-base | 47 +
...4e074e097ac04ed7dda08f0314a984954.svn-base | 62 +
...18608fbddab0057aa349563bfce7a7b99.svn-base | 299 ++
...534c4600707bd5ac91e094e6098f20e10.svn-base | 49 +
...0baa27d530f00f8bc55d17bed4dadc178.svn-base | 86 +
...eb3ca22ca789a851abad4f0f2e3752fff.svn-base | 21 +
...eef8836e9f2f062d0faa1084595a9d830.svn-base | 141 +
...6cc14d90ec74f2fcffb87eaa278f758a5.svn-base | 256 ++
...ff44b8980211e15c08927f4fca761e72d.svn-base | 193 +
...af805f358843a21697ee0f9999835ab7c.svn-base | 58 +
...b687ed242c05358e83cabd153e5f36bd8.svn-base | 20 +
...bb762cb8967a6bac0b48cd060c974ea7c.svn-base | 55 +
...e1196eea07a0574820445932b889b5e25.svn-base | 44 +
...859dda8123abb6ebb7033cd9de27746f8.svn-base | 242 ++
...a92925b68377688fd088b3ae90e735a55.svn-base | 4 +
...3807fe747509ff2e883dc9ed6c0ad471e.svn-base | 98 +
...eb204228a5a9f75b93e8d663d005bbf12.svn-base | 81 +
...35d09a29263d98fd0741ed447bf11db8a.svn-base | 90 +
...df3eaad407eb158ecc0426db56e71fddd.svn-base | 9 +
...2cd7927b51252f194d902a32b20d0fe0d.svn-base | 124 +
...53de78d6f3dda34325fab38ba1461ecc8.svn-base | 77 +
...ca58ded60938f9f32370a01310427a7e6.svn-base | 2 +
...1dd5fdf8b5da7a2f313157959e4b75735.svn-base | 9 +
...9eb2eb2a49098098c20b47fdff7bec7d0.svn-base | 52 +
...d0950a8028f07005db4bca847e8b2ff95.svn-base | 191 +
...827ccfb6a37830953c902d64ea944cd8d.svn-base | 11 +
...1c48212e9569a13bb6fc4715dbf015a46.svn-base | 8 +
...06bae5b8a198e029cc0fc42e89d4ecd0d.svn-base | 72 +
...2320af21c84af18f310d7f35090521b2f.svn-base | 97 +
...4862af372410286012dfdf316971ab2e2.svn-base | 22 +
...4a51bff8dcd3d668f7209549497209512.svn-base | 60 +
...28342b0a41b56a7c3115aace8b4c73c19.svn-base | 236 ++
...d09cf59aa3349a43bb74edf81e509216e.svn-base | 62 +
...f2fac8ace4b160c406372f0f0d77c2257.svn-base | 41 +
...d9853c6bb1976f4980b12660cf0d17d13.svn-base | 27 +
...a8008a407abd8e92a84c02961f0c804e1.svn-base | 31 +
...481940ef81a0e404b4712f28a84606fd5.svn-base | 8 +
...845d2146d8b4fecf634872efd2b9946f7.svn-base | 60 +
...37fee7a051b4bfa4c915e446887dab965.svn-base | 44 +
...c5f1ed377d2d86feefdb2ae4e58f79ee9.svn-base | 98 +
...8c013ad723cb4f540e1e8d3a362122c22.svn-base | 87 +
...02d438b7ec230f1ec681796987b5423c1.svn-base | 4 +
...2f61f8ed3375c6f7cb136bbd05f91a585.svn-base | 33 +
...a4d274761f39ea46bf56ea89a4998e837.svn-base | 171 +
...366dc73e836372fed630c61d70eda4232.svn-base | 25 +
...dacf1e2e20c98d8dc661db3fc0a82c587.svn-base | 99 +
...3d07bca0b75930717f70befd11c03d7f5.svn-base | 48 +
...27f1263e38bcb41b0a5b6c47ed2c03458.svn-base | 40 +
...40cbd24a36f24bc9f716d97ff7948f7cc.svn-base | 92 +
...c90fe93c16c19cf8a04906e3d230f1343.svn-base | 121 +
...5f3f3e22c1f073bfafc11e8a1ff546a45.svn-base | 1 +
...a7d58a2d38a85548534b6a8bf9ebcd4d3.svn-base | 60 +
...403984a104f3ecd1cde3bc17717f3195d.svn-base | 447 +++
...f684b407d0678b338394566e3fcfd9d42.svn-base | 96 +
...41b8ec24f10cfd7ef2390993db053a5dd.svn-base | 13 +
...bef57ca8c230881172effa82ec13a1328.svn-base | 44 +
...04e9f66700f2b19b73cca6358f845dbee.svn-base | 7 +
...3e72cce3b15f78b80d2e01ae4e840ca42.svn-base | 284 ++
...7d282379be80340866ffec7e113d0be04.svn-base | 93 +
...a9358a108e9893e6373d6367d7b5bd097.svn-base | 63 +
...aeef58db23ce230e72c479fd030f09049.svn-base | 80 +
...4a137f1d4a6420d607830ebf682565fb0.svn-base | 8 +
...6d8b08ff4deee86edabc68281eb2aa761.svn-base | 26 +
...d6d4011208c23f5803e9b2d47e4741762.svn-base | 96 +
...fcc8988414e015573f923439a7d4c436d.svn-base | 188 +
...39b0d717a0740bde098aef421172931e0.svn-base | 25 +
...78b3aa8d56c652daf9e7392072a05089b.svn-base | 5 +
...0b24ba35b977cec32e4b4a7a2a15f64fe.svn-base | 5 +
...140a96cce4d3b17e69da36c41ccec5d21.svn-base | 271 ++
...8a1bab462cda6e1cea30162e41d980fd6.svn-base | 38 +
...a125380ebd777853631dd19c39c833078.svn-base | 54 +
...34d171a294360c2c0b822b661307ecf5c.svn-base | 86 +
...a5501aeab80fd26539cb17ed51d6e4385.svn-base | 16 +
...0e67d7c540ee994071895fcc82ea4a536.svn-base | 52 +
...8666eab758050eec70b0bf011b787bd22.svn-base | 5 +
...01d5a04ec8892e50a9d1068234feb68b3.svn-base | 38 +
...ea7dd1c5f77fa37da94eba73aa4e8655a.svn-base | 158 +
...bab80c9061bc8c533bec08ed61313f245.svn-base | 51 +
...6a1cb2e70b9f49c5b60056a8f0c31e535.svn-base | 46 +
...1ae6e4e864c464aeb7699d8ca58ca11ad.svn-base | 353 ++
...8dc27da0bcdd2b2ba3f68ccff92a08c4e.svn-base | 40 +
...b275693322fe223e6bb21f68b387c664e.svn-base | 111 +
...c5b0e55a5d280c01f5ba84175746c6670.svn-base | 162 +
...50a869c38d9df717b755882d3d4fba5da.svn-base | 178 +
...663b36c1a3dd52beeaada9454b05cff52.svn-base | 67 +
...65d6c9834818864e94ce6e312aa2a67b7.svn-base | 55 +
...8935ca0387070ea4a67edb3d619f2c52c.svn-base | 103 +
...0de5dd318956d73491271fff4d613b8f6.svn-base | 101 +
...202fd344afff9a31caf97f8185a3a32b7.svn-base | 63 +
...3f03908ff2845be69750fc79cee39911b.svn-base | 33 +
...c50b27b5dcf3d3910d3cff5d33b44f849.svn-base | 222 ++
...8bb1fb13e5def7fe4f3e07ed2abf8d76e.svn-base | 88 +
...a7fd2dfd1b789ed02f487f7403096c840.svn-base | 479 +++
...822110dcbf1f382143d5a877c61ec4fee.svn-base | 67 +
...e252d7ed7287077f79b78b686a9b4aaa1.svn-base | 153 +
...5cbaaada678e87728ca356f20a02116c0.svn-base | 104 +
...f369f7d04b4b020958f75e075db449ae7.svn-base | 345 ++
...8ac132bfc8b23390937e87d0c58902b52.svn-base | 33 +
...3db5c43710acf7e60612fe72744ad4e20.svn-base | 57 +
...2820998bd3b2bb0a673fc1c4912af40ce.svn-base | 160 +
...99aa51d1ef50a7b8d7b8100fcdbaf1ab7.svn-base | 18 +
...a0fe52dba7818253da9131d03d9481406.svn-base | 34 +
...c9ad46b1253e1ef181a719dd4776db3e9.svn-base | 131 +
...d3b71584cf45c3ea68f9eef9d142db43a.svn-base | 3487 +++++++++++++++++
...e25255a50bd65a58be00c99a345db66a6.svn-base | 143 +
...14df9ce81e129eb39ba943cd52b901461.svn-base | 43 +
...63d95380821f9ede591b1d4edd50b1734.svn-base | 62 +
...7d82fb46c705dd83275d7af5804b89e72.svn-base | 4 +
...65d0ac04fe19f8233d9823f57230d2751.svn-base | 86 +
...eecabcbf96383384d641b5ac70af2d741.svn-base | 592 +++
...faa71fb1b5a78c6b29cb7eeacc9d946ca.svn-base | 147 +
...d2212fed985f763417899f7d027bd7624.svn-base | 1888 +++++++++
...fe9a5631e1775ae3148f392bcecf9810d.svn-base | 10 +
...11b92e329a4c7f42a1a4482984549452e.svn-base | 236 ++
...c84883eae776ffcd5c34f7d2287d1d64e.svn-base | 33 +
...e6f73afb74314ae96ea02d60873a3924b.svn-base | 139 +
...c9870e83ca5586e5fcc655f5e598bf056.svn-base | 12 +
...a2822815af226fced2f1ea3ed0bdce14d.svn-base | 35 +
...30718fd2af4d75e902ed17e43f4d4a7a3.svn-base | 9 +
...ce85954f7658922149992c41f561dff23.svn-base | 41 +
...b8e59b7257438ac43b697595693ed67ad.svn-base | 82 +
...6d8fd912e9e92a03b65f428d6c1ca67a8.svn-base | 130 +
...f936336e6b1980b10b3e3a1c5b25cf979.svn-base | 4 +
...86fa908f28c65e99fb9244f7215732d3a.svn-base | 57 +
...3356e109ca02d690a0f3e112c1b7160a9.svn-base | 210 +
...7e38dcb58a637660153d0975bc1a12435.svn-base | 46 +
...b09dd6913b8db7aa1101567e654d5688b.svn-base | 8 +
...b10658b7f1d9a676fb7ac48039ce5811d.svn-base | 72 +
...e4dd7928626cfb64f2aa60c02f20b3377.svn-base | 43 +
...95ba289f2814d142867f8b3c8b656bcc6.svn-base | 6 +
...5b2dc0b67c16cc0ca0969ccc3beced3b5.svn-base | 60 +
...0f90ddc71ac1e55d805509de083160973.svn-base | 121 +
...99f309c79bfe065f74852ad8472550a64.svn-base | 58 +
...bdf356528e88b81a4d056ef101c3f2dab.svn-base | 351 ++
...46311ec1a7fb33f7af3bf321e12849b3e.svn-base | 137 +
...b77af890ae642df0aa8057fec9c270362.svn-base | 4 +
...b9323a898bdd54e298af7d72c23e17c92.svn-base | 122 +
...b84435287bed433151d37fdb4ea278134.svn-base | 48 +
...69f06a10e8753aa29615c830eeb6a93d2.svn-base | 25 +
...bd1c8f91e144ffc3eccd5771e0106b89e.svn-base | 195 +
...3ced3bcd5ef55db9e89d8f8ec57c08169.svn-base | 189 +
...799b68f61c0ca2c70c53a76bf8682d53d.svn-base | 240 ++
...b3f753b8db98c4342a8078aa3838834fa.svn-base | 119 +
...cb0a99dea745caf06399d529660b36d78.svn-base | 73 +
...9bea8c3724f745fe7d08fa08a881f29fe.svn-base | 148 +
...c9aa74a9ffcb94751abbf611552780c8f.svn-base | 47 +
...df0fa01fadb0e50628107f55f6ea1526a.svn-base | 132 +
...7f38c81b56214f92f20e124e9ca1b93d4.svn-base | 16 +
...76990d5ed98122019a852685bff9ecba1.svn-base | 24 +
...a1c83992313b5e816175c43d5072d5678.svn-base | 56 +
...01582adb9354ba950e8d577cc223c2bea.svn-base | 1229 ++++++
...b2ae73296a480cbab67c3ac8aea40cd6b.svn-base | 115 +
...be57c23e1a91c62285e300272fd3623cd.svn-base | 410 ++
...e0718beb6b5b49feaa529021829d3b47f.svn-base | 174 +
...fd04f2898b7d2946a2cf44f982d178eb7.svn-base | 63 +
...40239ce29e87a077e64aa7c8159a3e928.svn-base | 200 +
...3e7fb2a59f42cc32977cb9631c6a7c263.svn-base | 4 +
...5304752f27eb7b181c9c77a076688d4bd.svn-base | 374 ++
...9336a04d99116d54ff6266e992cf946cf.svn-base | 100 +
...987b43f6444bb495946acb79428262a05.svn-base | 910 +++++
...f9a5b15112cc04add9c28694ac015a8be.svn-base | 62 +
...f16d11b427605727055ca0a7388f3220f.svn-base | 29 +
...176794c6dc0a3cb9beb67c4b0066f0ffe.svn-base | 17 +
...6c0f56252d82165dbd9b637f5e8f975a3.svn-base | 85 +
...15a45eb0ccc276f8fa20041907e256405.svn-base | 5 +
...582163ba6b008a2abcbdea0fc2dc8a0c3.svn-base | 38 +
...fd5b278c287ae9d197d983f51fbdc15ac.svn-base | 136 +
...9627ec9f1cca305600e859c660e059155.svn-base | 77 +
...b910200a3316573e71c62be3a379935e7.svn-base | 34 +
...2abcc4bff624523c02c220ea0387d4b9e.svn-base | 146 +
...416943da022b6cf12f3f0251b1236ed3b.svn-base | 100 +
...2f29b11c85b630929fef7c82b0ab1197a.svn-base | 34 +
...cb6580dd798aadb4c3676c4966ca070a8.svn-base | 27 +
...c85ceea072453a3db80d7c58e973d4d5d.svn-base | 22 +
...1b6d39cbb78fdddd103eede2ab2a89718.svn-base | 18 +
...6d80645a60d647632b7716ea9b6d69ddb.svn-base | 29 +
...46569f6a969f86e42624dcbffa80a4f16.svn-base | 22 +
...f40fa2604d8db9e96c1083d511736415d.svn-base | 154 +
...92043dfc9080641288182ff8e6fd6d49e.svn-base | 301 ++
...23f8ac6c06f378c7cdade8f9337369d80.svn-base | 45 +
...486579bf0f1959fd5de612ce9e97ae022.svn-base | 56 +
...9d9d70dfd78901ecb2dbbded614afd0e8.svn-base | 119 +
...529b193cf39dd8b46dd9a6f7ef966e58b.svn-base | 119 +
...e1e6a2ec8e057e55d8ee429331f287ad8.svn-base | 58 +
...6407252911a87b272f7f64f497d17542b.svn-base | 321 ++
...9c2313a6abe2a388f97c0cb700658ce2d.svn-base | 50 +
...b64902191465d27dc97c32019918ed5b9.svn-base | 9 +
...62cbb4d1bb07d1f0370afa81623f393ec.svn-base | 5 +
...9985e3681afcb3eaa56dda606f6e0d51f.svn-base | 26 +
...506065c9c112ebd441d0cfaa4f4a85134.svn-base | 73 +
...c5b0f9db52ddd0cfc5ff557e651b936fc.svn-base | 55 +
...314f67cb894878b7b487f342851d79a87.svn-base | 63 +
...c1bd3688d4378ddef823babd3dfb0e02e.svn-base | 7 +
...12ad648d170eb11a43db7c28fdd223a1c.svn-base | 62 +
...802d0730e9010a072b97492835824bb93.svn-base | 433 ++
...bf60b75d8ef6d0279591a1e26fcd8f164.svn-base | 169 +
...dabaa27bdbb76e57d2a73f9d947cd1db5.svn-base | 198 +
...390b73dc27ebd1a445e6c10f3ec070506.svn-base | 190 +
...0e294528fae314f41e36b5e80aa5ce77c.svn-base | 57 +
...808888c4657fd023c4a36410c8bda7642.svn-base | 53 +
...edc77f15ddf9b33e6141080c2cfa6a8ee.svn-base | 48 +
...707c94e31ef151838b9aa2d41b9738b29.svn-base | 57 +
...a26094cfbbd7697f23ff12b8a8296034c.svn-base | 496 +++
...e9812e4e8a225bda8fbbb01b98335b5d6.svn-base | 25 +
...e2be2bf84ef422f6d46fee1c6d72927db.svn-base | 20 +
...eb223e05c1256bc2d323cfa1d3defaf89.svn-base | 80 +
...8ad5651d411a686ad381c517573db21e9.svn-base | 40 +
...03d3356b5564ba6e3a702f2c4e7fb91bd.svn-base | 53 +
...a6e4869e6ce75ae57cbae6ff30fb992bf.svn-base | 95 +
...384da66767c5365f798b9e8c45711d2c8.svn-base | 75 +
...79a1db7242bd91c78fe029c7589d017a8.svn-base | 48 +
...e084ceb657f0c2ad3d71422f9542bfd3d.svn-base | 13 +
...7317ad7ed1c9f5de6c68d30046dbe55a3.svn-base | 22 +
...5596baf09e485ec88b49dd9fe9be838b4.svn-base | 2088 ++++++++++
...d06fa9acd7a21cd0f9af3886cf09c04f7.svn-base | 36 +
...5fb0107cbcac5a7bba48946987c1b1f89.svn-base | 58 +
...8e659091bf86505b20ee145ef9b4e5a6a.svn-base | 44 +
...6deb51ba979ae080f7e5fa558450d24d6.svn-base | 31 +
...b191804d9f0d6a4d12eb7e1bd38aa042d.svn-base | 7 +
...1087a770c4b322620f99a90f745126be9.svn-base | 87 +
...3c6fd7a857bc59bde7d5bccea47d2020f.svn-base | 26 +
.svn/wc.db | Bin 0 -> 1060864 bytes
.svn/wc.db-journal | 0
580 files changed, 69806 insertions(+)
create mode 100644 .idea/goProject.iml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/workspace.xml
create mode 100644 .svn/entries
create mode 100644 .svn/format
create mode 100644 .svn/pristine/00/001ae31cf129372b636ccad5355eca7cd5992f37.svn-base
create mode 100644 .svn/pristine/00/00274e716eefcbc7222fcf148fae2d4a027038d1.svn-base
create mode 100644 .svn/pristine/00/0096b6776a09918ae8e11a6ea4ea0baebb972248.svn-base
create mode 100644 .svn/pristine/01/01089319b44c6f1155fa6d3b8d81d7557fdea2a1.svn-base
create mode 100644 .svn/pristine/01/010cd221ec8c3741fb44e0c141d45af65b1dcf19.svn-base
create mode 100644 .svn/pristine/01/013419d9030f7fb4c2de649a85be0862d57334ba.svn-base
create mode 100644 .svn/pristine/01/01fbd56a6bc1d05c1f484952a04efc5e992d3c89.svn-base
create mode 100644 .svn/pristine/02/0299147d74eace2e9a84bcbe81bc0966d9a44600.svn-base
create mode 100644 .svn/pristine/02/02bcd00feee3f43be99fed3c1fd0412e261ae3a5.svn-base
create mode 100644 .svn/pristine/03/033f93a5ed351569e457445896fd1913ce46d45b.svn-base
create mode 100644 .svn/pristine/03/03df81ec69165cb7077f9e740559446368aca1f2.svn-base
create mode 100644 .svn/pristine/04/0418a758fbce45201919045075139dc8513be286.svn-base
create mode 100644 .svn/pristine/04/044e3ac017ca5d27710d505ac314376753225cfc.svn-base
create mode 100644 .svn/pristine/04/04cc1937beadc6d8dace22ef80979ab50388eeea.svn-base
create mode 100644 .svn/pristine/04/04ff71b4d0991e86509f1059a6f59d487d6eadbf.svn-base
create mode 100644 .svn/pristine/05/051936fe62906601a10b242b5729b54e02e6890c.svn-base
create mode 100644 .svn/pristine/06/067c32d6d970c791745423200210d5c8eced9132.svn-base
create mode 100644 .svn/pristine/07/0782015460cfe541898e77c9fb5904023dcd9457.svn-base
create mode 100644 .svn/pristine/07/07ce17462368c2b1dc512b9b3abd7951d62168e5.svn-base
create mode 100644 .svn/pristine/08/08ab382d97d7dc9708f61a91bdf317d06b7b7d83.svn-base
create mode 100644 .svn/pristine/09/0973b54e789e52c6207035406c7a797712e93165.svn-base
create mode 100644 .svn/pristine/09/09b7f50515939483a29f46f368d7bd7db0165b49.svn-base
create mode 100644 .svn/pristine/0a/0a32a7aadf4e5244aa44094b27c6e4e39d8a1f2d.svn-base
create mode 100644 .svn/pristine/0a/0a359deb9b9471a4ea96b66c1cc364911ab54b99.svn-base
create mode 100644 .svn/pristine/0a/0a5860746a4b445d18be34fff4f29b1e4b180b35.svn-base
create mode 100644 .svn/pristine/0a/0aad8def9322e065863083d01d249ef44cf69dc5.svn-base
create mode 100644 .svn/pristine/0b/0b64d992d48171632e253b32b808a1222c5e7681.svn-base
create mode 100644 .svn/pristine/0b/0b6d198d02242d905fb9068a5756c87c3a5aa2fe.svn-base
create mode 100644 .svn/pristine/0c/0c649c8389b0629d492c0cc4dab91d9b280686d2.svn-base
create mode 100644 .svn/pristine/0c/0cc6a8594a211ca755865be522ee4fc139d7b3f1.svn-base
create mode 100644 .svn/pristine/0c/0ce1ecad1add98c087081650bab4b1dc4ba8424b.svn-base
create mode 100644 .svn/pristine/0c/0cf6873b2c63205e8f54bb6bb60b43880f54c4a8.svn-base
create mode 100644 .svn/pristine/0d/0d81a7654b3ab7b1fa88a882ac9120820be781d1.svn-base
create mode 100644 .svn/pristine/0d/0de3f1598f1552816faf3d86834fb1b66bf8bf50.svn-base
create mode 100644 .svn/pristine/0e/0e6c90a79a2d82d7163bf69aa24a408f279cd51a.svn-base
create mode 100644 .svn/pristine/0e/0ee1b8980db1cb87c67f3c144daf44fb3b086161.svn-base
create mode 100644 .svn/pristine/0f/0f30963356a1fb59be2104ee2e958491fa209bf6.svn-base
create mode 100644 .svn/pristine/0f/0fe95ca68a7edc2b57740acf0aacde3feac27ecc.svn-base
create mode 100644 .svn/pristine/10/107fc1aabad97f3332dd60150062cf10fd36945d.svn-base
create mode 100644 .svn/pristine/10/108dff723727057f2372bcb30ec7552664b06138.svn-base
create mode 100644 .svn/pristine/10/10a0f5439f7d2565fa8e1274fd45c809c65da569.svn-base
create mode 100644 .svn/pristine/11/116309fe30c7ac55d6efe3eaf1f188a4151a7571.svn-base
create mode 100644 .svn/pristine/11/11dd611238f6e4771bc74430cc3f2bee6b274238.svn-base
create mode 100644 .svn/pristine/11/11ea234943ccae37879b6dbde2815a17b6504038.svn-base
create mode 100644 .svn/pristine/11/11f624645ee771a7b2811130a3b416d486e6e892.svn-base
create mode 100644 .svn/pristine/12/12d698470913bfc03a551aa87944abac426b9072.svn-base
create mode 100644 .svn/pristine/12/12f5e440c04874ab483587453f0e175feeb4c956.svn-base
create mode 100644 .svn/pristine/12/12f75adbec35d99e08a5f0ff52f0c36225adff02.svn-base
create mode 100644 .svn/pristine/12/12fec7f3f1013e25716d622f56b3972e13598eea.svn-base
create mode 100644 .svn/pristine/13/133b571edb1ebc33483b575fba2f0df647af9e8a.svn-base
create mode 100644 .svn/pristine/13/13a7a5172d7c0e0fdc2fe718e7d1e71f371e8ac6.svn-base
create mode 100644 .svn/pristine/14/14de84ff1959026fcd250504d7000e59f58e3b41.svn-base
create mode 100644 .svn/pristine/14/14f1b3374c1cb8cdd4b7ad9f7efe545734fe2675.svn-base
create mode 100644 .svn/pristine/15/15c0d6e3d729f98b5b8564f2033328f4aee93dc0.svn-base
create mode 100644 .svn/pristine/16/1651822b5dae47034a6e1eca1f65ebcdd985ab61.svn-base
create mode 100644 .svn/pristine/17/175c67ad8c4ec0d0b345954e5fcd054c655fcda7.svn-base
create mode 100644 .svn/pristine/17/17893865ee184352bf16c2e23e049560a9b6ba80.svn-base
create mode 100644 .svn/pristine/18/18086fba2a253139cdd05cf26644b4f525c60e99.svn-base
create mode 100644 .svn/pristine/18/1838ff95fb3a29c19e78e2e5e1e308e4bc2551c4.svn-base
create mode 100644 .svn/pristine/18/1849d81e98b05475fc80c58a3255322d410a1a84.svn-base
create mode 100644 .svn/pristine/18/18e8f4fcc246b38d375d7d7cf3d46f677afc9de1.svn-base
create mode 100644 .svn/pristine/19/19cd06f67349e079d14ba9d6e284cd8a2cbd2ca4.svn-base
create mode 100644 .svn/pristine/1a/1a85336be2fbc6102cfdbb3d5e7b672995ea4226.svn-base
create mode 100644 .svn/pristine/1a/1aeca629abfb9fb4344aeefa35ceadca73f1fe4c.svn-base
create mode 100644 .svn/pristine/1a/1af88023dbc796a3f5f0281152a47b2d363859d6.svn-base
create mode 100644 .svn/pristine/1b/1b2c410b7678eef959ff8f8c0e69d4051e45ed17.svn-base
create mode 100644 .svn/pristine/1b/1b511d8dc10711a9b500c6dea251529f59d249f0.svn-base
create mode 100644 .svn/pristine/1b/1bb1d81f707f332983e7042674e7c933e71d089e.svn-base
create mode 100644 .svn/pristine/1b/1bdd83307433453f47a849b07a75501b86ac53eb.svn-base
create mode 100644 .svn/pristine/1b/1bf0ed25a847601c48c478898d552ab339455646.svn-base
create mode 100644 .svn/pristine/1c/1cb4f4122548d93244351bbac432d4a7cdde9667.svn-base
create mode 100644 .svn/pristine/1c/1cbdbfc80bd20fd584e9675d554ea02cb7d35caa.svn-base
create mode 100644 .svn/pristine/1c/1cd69be06a95554c30263afa7ce43d3775f1dcdb.svn-base
create mode 100644 .svn/pristine/1c/1cd8027881b113926160df0087f10a47ea9e87ff.svn-base
create mode 100644 .svn/pristine/1c/1ce84cb99036df716050665854c27a1925523227.svn-base
create mode 100644 .svn/pristine/1d/1d02ea53e36d220fc9a9e9944b67bc4d96bd8d26.svn-base
create mode 100644 .svn/pristine/1d/1d4e0f007677509afe5a28cf69b7241d9675e0c1.svn-base
create mode 100644 .svn/pristine/21/213b0a00bea424ffed61b3775e9a3885c7c78fac.svn-base
create mode 100644 .svn/pristine/21/21a7c96834766c7d74d55dbfaf1b49771fd9e489.svn-base
create mode 100644 .svn/pristine/21/21dc46aabd801627575e7862f59be14761f21a15.svn-base
create mode 100644 .svn/pristine/22/220fecaa6504067877bec738054b2ee97658da3d.svn-base
create mode 100644 .svn/pristine/23/2323503bd48538f9d2f8b36722a664b308762e83.svn-base
create mode 100644 .svn/pristine/23/23cb9734e39cd278edd81f86a6b942d541ea2921.svn-base
create mode 100644 .svn/pristine/24/2408308d2e72184a45660ed9c67c714a06107c62.svn-base
create mode 100644 .svn/pristine/24/242c687d5a16af36ce250d440564fc2b747e6dd4.svn-base
create mode 100644 .svn/pristine/24/24d43d9907392c148b50ae48efa6d7f9e9746822.svn-base
create mode 100644 .svn/pristine/25/253842466dd2f7a93da426d59d796617815b5714.svn-base
create mode 100644 .svn/pristine/25/25b8521c8aada772e1f6465d18604e289c9e5489.svn-base
create mode 100644 .svn/pristine/25/25fe816e9e9fd164ec610c7921a8639c1dcbfb15.svn-base
create mode 100644 .svn/pristine/26/26022c8a11741f20169313a7438cfe711b0ee295.svn-base
create mode 100644 .svn/pristine/26/2621e7b98a6ac756be9f2d95dd9e284ddb2338b4.svn-base
create mode 100644 .svn/pristine/26/262ac8472b6314d517f3a9c48c61c54f3b4d315d.svn-base
create mode 100644 .svn/pristine/26/264f287a04ade2aafd862fcba87d65aa33d2dfa4.svn-base
create mode 100644 .svn/pristine/26/26fd4cb975dbbbc57bf60a2d6c23dd8242dce9b2.svn-base
create mode 100644 .svn/pristine/28/281351a336934c29f0bf81f0e3cfb3ba03e237b0.svn-base
create mode 100644 .svn/pristine/28/2872d3f11847c786465856bc05af9651a484188c.svn-base
create mode 100644 .svn/pristine/28/28f055a2b9e8a852f03d50095156e421917e10b3.svn-base
create mode 100644 .svn/pristine/2a/2a4adce6fe53177181f083b4ac4b0cd9fba5b1fe.svn-base
create mode 100644 .svn/pristine/2a/2a53f94905747f4fa5f73ac48126d3788f20ea2b.svn-base
create mode 100644 .svn/pristine/2a/2a56a5647a58e684f5d5c35587c678482c56dc2d.svn-base
create mode 100644 .svn/pristine/2a/2a62442565a8992159b26fd4bcb62dd98d3f8e35.svn-base
create mode 100644 .svn/pristine/2b/2ba46d976f1f72118d5726c9a45ee3c678037629.svn-base
create mode 100644 .svn/pristine/2c/2c280202647fe7e9eb22c3f13cd5afd8135b0dab.svn-base
create mode 100644 .svn/pristine/2c/2c42831a7794d3b03ba2af46e7a5709253508107.svn-base
create mode 100644 .svn/pristine/2d/2de0a01a0fa2a5a57e9f7e655eb3d363f14c41be.svn-base
create mode 100644 .svn/pristine/2d/2de12c2ba27e67d1efdfc163a25f3b7bd611f8a6.svn-base
create mode 100644 .svn/pristine/2e/2e2532365bcd2cea0e001934e67db11e0fea1405.svn-base
create mode 100644 .svn/pristine/2e/2e766b25919f4eac85c32fd101e5bd303ef1190c.svn-base
create mode 100644 .svn/pristine/2e/2e8e3f2c21083bfc1741db5df016b198b53ae6ad.svn-base
create mode 100644 .svn/pristine/2e/2eb9ec388af8b1eec3c306160021488411784adb.svn-base
create mode 100644 .svn/pristine/2e/2ebc67fa9c1257d723c197f604ecb9c540c228fd.svn-base
create mode 100644 .svn/pristine/2f/2f14ad8b60fa320c31dece98ac92ee259e9a5f3e.svn-base
create mode 100644 .svn/pristine/30/30949ac53c528a2ecc3d58647e3be3906413ea67.svn-base
create mode 100644 .svn/pristine/30/30b3aab878ea7aff20885d6b00cc935dbd706a3e.svn-base
create mode 100644 .svn/pristine/30/30ba2f04f4755f5db8d0594c2929c51ee463b213.svn-base
create mode 100644 .svn/pristine/30/30fd49aaef962809ed3ade0ffa38bd43ad47b521.svn-base
create mode 100644 .svn/pristine/31/313f27b5bd4317d500dc2743379a8be288c087a9.svn-base
create mode 100644 .svn/pristine/31/3167307a52e20e4a543ae33d5269808f02e5b7e4.svn-base
create mode 100644 .svn/pristine/33/335a13f982390c2ec9a716fcddcea8bc20697680.svn-base
create mode 100644 .svn/pristine/33/33b2559f92484c30f0522d74cc475fcffe1f82f7.svn-base
create mode 100644 .svn/pristine/33/33c823dd0646acce265d7166cd02d78a6807aea2.svn-base
create mode 100644 .svn/pristine/33/33f4735ef28dd736d756c6d320e069c3ab89f068.svn-base
create mode 100644 .svn/pristine/34/3439bb7d1781aebf4bed60ed3aadb529219c3f32.svn-base
create mode 100644 .svn/pristine/34/343fd5ed458ab13b56f9ac7761adf383671377ed.svn-base
create mode 100644 .svn/pristine/34/3449f3eb7da2660d83da36bd4e0b728e917c7f96.svn-base
create mode 100644 .svn/pristine/34/34c4995e93e1d7fb867c6043db15d57863b64727.svn-base
create mode 100644 .svn/pristine/34/34cd0a6c1e01175f811d01e6be3886accfb3919f.svn-base
create mode 100644 .svn/pristine/35/3547deaad7e807c519e9f84e8e45315bcb11bee2.svn-base
create mode 100644 .svn/pristine/35/3566bd2849a9eca9f553cedecc4a9b2ebd621b23.svn-base
create mode 100644 .svn/pristine/35/357e65a8770e13e0ad7e76c3c6635a87600816b2.svn-base
create mode 100644 .svn/pristine/35/35d65336c7541bc544702d797fcbda5918ed0177.svn-base
create mode 100644 .svn/pristine/36/368ca45601698339d1c23760a5460bde5c1412b5.svn-base
create mode 100644 .svn/pristine/36/36d0e387eafa0d8f7a60cec4a9b30a2133bcc6bb.svn-base
create mode 100644 .svn/pristine/36/36dd2756b063ca1786642aa7e12792c0a26d104c.svn-base
create mode 100644 .svn/pristine/37/370a9eae2ee1aaaeff3dcc4e23bb2a1391220586.svn-base
create mode 100644 .svn/pristine/37/374dfacb825adc910983b41ee6e2df86611ca117.svn-base
create mode 100644 .svn/pristine/37/37b917300c968fc5f809e08ddcf2abcc2774fd2b.svn-base
create mode 100644 .svn/pristine/37/37be33c1543987b2fc1e5ad1e0041ffbbef1231f.svn-base
create mode 100644 .svn/pristine/37/37e94747cff7c5629f6a5f38855e9ad2891bca8e.svn-base
create mode 100644 .svn/pristine/37/37fdb38c232c02a13b29a2b8ea947d48e87e0798.svn-base
create mode 100644 .svn/pristine/38/384faa85c664eb83dc8772b69254ad4263c18541.svn-base
create mode 100644 .svn/pristine/39/39a09255683add574e0b3b1b5c7e521de4a47ad3.svn-base
create mode 100644 .svn/pristine/3a/3aea22b2166c4d38707ec9cc9c910dd1e4ff2dd8.svn-base
create mode 100644 .svn/pristine/3b/3bad0f0187ec9411b0df5744d9cd02879fa239f4.svn-base
create mode 100644 .svn/pristine/3c/3c161a0814b5fbe104eac0a7b7d76bf8dd007800.svn-base
create mode 100644 .svn/pristine/3c/3ca8972a3836e96a64416fbbd2ebafdebd1fc2ab.svn-base
create mode 100644 .svn/pristine/3e/3e543ef3da7294f5fed68348b9d711e4e403aeb2.svn-base
create mode 100644 .svn/pristine/3f/3f2828af3b3e887131b06e7b527762a83a3c41db.svn-base
create mode 100644 .svn/pristine/40/405762ee5ebd4d12dbdf32a30bfb9bd84a970159.svn-base
create mode 100644 .svn/pristine/40/409acfe0b7a243190727cdff70cde0a7dcf33931.svn-base
create mode 100644 .svn/pristine/41/414778273450f16557c41cc40bc68d5bca11839e.svn-base
create mode 100644 .svn/pristine/42/428d4b97237af34809acbd8293feabe883b1d689.svn-base
create mode 100644 .svn/pristine/43/431951efd695edc9cc00309e90205cafdb4ea415.svn-base
create mode 100644 .svn/pristine/43/432489717638beef3ca372b2de090fd58b2e17d7.svn-base
create mode 100644 .svn/pristine/43/4338e30fb77af67f2f9564918a01fa309f8f6815.svn-base
create mode 100644 .svn/pristine/43/43442b142f5c5969f7878c2074d3b3ebe0f9c003.svn-base
create mode 100644 .svn/pristine/43/4385e6c1186639ab7ed02dd5ccd2c781cf61b193.svn-base
create mode 100644 .svn/pristine/43/4394e6533451632d39ca579614e8ddfbf9781d0f.svn-base
create mode 100644 .svn/pristine/43/43a87b7137557b0aa604619fa267109dfadd8834.svn-base
create mode 100644 .svn/pristine/43/43f852c1515a55d48e5d25081f9210b9da4ff66c.svn-base
create mode 100644 .svn/pristine/44/441ecb83b8c1a3af9e234f21ac76c082a4f9ff7b.svn-base
create mode 100644 .svn/pristine/44/4455e0cfdc1b824c9dcb29ac73ba4313e7b94906.svn-base
create mode 100644 .svn/pristine/44/4472e6a7a56519f9549a2f2f3f364207e68b78bb.svn-base
create mode 100644 .svn/pristine/45/452216f78217ea55998820ec3ca6c0e9ae15c4f0.svn-base
create mode 100644 .svn/pristine/45/454997784756d5cf8e2dd0c2ef3ccb48f3739826.svn-base
create mode 100644 .svn/pristine/45/45a09743370b259aefd77d242d38fd7769811a8d.svn-base
create mode 100644 .svn/pristine/45/45b8bbbab2a9efeb7b70840597892f85147de079.svn-base
create mode 100644 .svn/pristine/45/45f0c43c59968de8708cb631ec180d949e04a2d8.svn-base
create mode 100644 .svn/pristine/46/460e1ba3b9bd0b80cd60485a6013941777b27d7f.svn-base
create mode 100644 .svn/pristine/46/462e834bc4c52b9546cd5900c63f09387213c2e5.svn-base
create mode 100644 .svn/pristine/46/46fe9b43a26885328f556159b055b3d369732600.svn-base
create mode 100644 .svn/pristine/47/47e1f67a37d3cf0affa5dd7f1a866f5375ac5629.svn-base
create mode 100644 .svn/pristine/47/47e800dd36b3f0c082e6782f864014eb4e07d2a5.svn-base
create mode 100644 .svn/pristine/48/48003ffa1a6493e340cfad0e3092a40126a4aece.svn-base
create mode 100644 .svn/pristine/48/4852aa2721098eea260b5d302d760e536bb7e64a.svn-base
create mode 100644 .svn/pristine/48/486e1cb4731af6df40aa03de3ed2ecdba22db264.svn-base
create mode 100644 .svn/pristine/48/48765b4ca5ea1ebef8ef05e1ac43f034ae2cc57a.svn-base
create mode 100644 .svn/pristine/48/48c5b123aaa4f5248637d444f7ab2c0fef970cc8.svn-base
create mode 100644 .svn/pristine/49/492bfe99e7af5f1f82645c1b1302f1536f95c33f.svn-base
create mode 100644 .svn/pristine/49/496a3674ea3bdc4d3c6456f7cd29c29cd7bd701d.svn-base
create mode 100644 .svn/pristine/49/4995fa2b02485de6eb3a2c938963067ee4ef19bf.svn-base
create mode 100644 .svn/pristine/49/49ee5106c29cff02591a87a5b23b6d636baf73e0.svn-base
create mode 100644 .svn/pristine/4a/4a49ef451d4b9f74fdb2c8830143bbaec17f3ce3.svn-base
create mode 100644 .svn/pristine/4b/4b8e1ac3d261e7448019224293b8c2f300ee0ab3.svn-base
create mode 100644 .svn/pristine/4c/4c23f994a6d4b535e3554239a36e580922efb062.svn-base
create mode 100644 .svn/pristine/4c/4cdf5c756ca8b6b4c1684486b413f058cbcdef5b.svn-base
create mode 100644 .svn/pristine/4d/4d9ed17b45d8fe9611097a5640452068f52cfc06.svn-base
create mode 100644 .svn/pristine/4d/4de7d0e1719fe7c5227e762a9cfdbfea79af5c81.svn-base
create mode 100644 .svn/pristine/4e/4e0d2175915e4e0a382656f419b23ec37c1dea9a.svn-base
create mode 100644 .svn/pristine/51/5134bf90a024b2d740a38545632f8b07a313f9ec.svn-base
create mode 100644 .svn/pristine/51/51904f3f8b846194d5b8e73a078da71adaae6dfd.svn-base
create mode 100644 .svn/pristine/51/51e48b01a62c7b4795266420a89faf8955b3a29c.svn-base
create mode 100644 .svn/pristine/52/52095a281285493617e456ee5193122cba2fe3e3.svn-base
create mode 100644 .svn/pristine/52/521f814a989f3a71d3af9af1cc1514017f4c3b2d.svn-base
create mode 100644 .svn/pristine/52/5237995ae7afcad71966e2a8f30ed0f0ee23991f.svn-base
create mode 100644 .svn/pristine/52/526ed4f4997979f5889d26f7a025ec34dd3405f1.svn-base
create mode 100644 .svn/pristine/54/5445c6a66d28f994d025ce139e3a8e09bfb68196.svn-base
create mode 100644 .svn/pristine/54/54a0e682fd6262e24fa94fe5e10814532f88b5bf.svn-base
create mode 100644 .svn/pristine/54/54b903c8c997feaac3b622c39ef0886b149d80e8.svn-base
create mode 100644 .svn/pristine/54/54fbc9bfaa37789ec76a10782c878db5e00b7e43.svn-base
create mode 100644 .svn/pristine/55/55d454d62218b6c17d558654dfe26659205489a0.svn-base
create mode 100644 .svn/pristine/55/55d4f6929df5269adfb1bb29dba1fb1b34ce16bd.svn-base
create mode 100644 .svn/pristine/56/56917ecd3dd2f5232b9c9c3ca1dcfaed71e2c9bb.svn-base
create mode 100644 .svn/pristine/56/56f885374bb697f0fe69c523d081a0ef9645d4bf.svn-base
create mode 100644 .svn/pristine/57/576810f1d094644512c078a85a8cf10b20959f04.svn-base
create mode 100644 .svn/pristine/57/57ed580996c3cd3c94a7b7422b369a6540ad167a.svn-base
create mode 100644 .svn/pristine/58/587f9e024e52f1a9c27470de900d08085d5fc9d1.svn-base
create mode 100644 .svn/pristine/59/5921c843b6a9a0d075c29e4af206bb73d7e042a4.svn-base
create mode 100644 .svn/pristine/59/59644769e5532c6fa13a4bdf8e311311407deff0.svn-base
create mode 100644 .svn/pristine/59/59761351ace94d6dc0a08b6752112ec23c9e90ea.svn-base
create mode 100644 .svn/pristine/59/59b53e67e3409c1fc1075865f0d23cd455d28d1f.svn-base
create mode 100644 .svn/pristine/59/59bf7d0767b223adba34dffed1cabbbbbcb8210a.svn-base
create mode 100644 .svn/pristine/5a/5a189554277f63f045f0d9feff1a77292f1eada0.svn-base
create mode 100644 .svn/pristine/5a/5aaba2322ee53e31116a0cc59afcda10b566881f.svn-base
create mode 100644 .svn/pristine/5b/5b1d2eb77b85e4e36232243c7273ed32a23df5dc.svn-base
create mode 100644 .svn/pristine/5b/5b7144648d38e77bea09228526e4a1cc66a86fd9.svn-base
create mode 100644 .svn/pristine/5b/5ba8ba3ff47876b2475132ee02919a860a69a8d5.svn-base
create mode 100644 .svn/pristine/5b/5bae2a2351dc932639f48484b5f38da44c769cab.svn-base
create mode 100644 .svn/pristine/5b/5be359c1bf55a499ca0575b8b4af358bbfbb7565.svn-base
create mode 100644 .svn/pristine/5c/5ce606a1bf41c73ac8d2169614eb70b18e7551ae.svn-base
create mode 100644 .svn/pristine/5d/5dc12fc1c712eed283d8593d10c63d946be7337c.svn-base
create mode 100644 .svn/pristine/5d/5dca3ad5e01acc3892a93342d49523e7afb43b05.svn-base
create mode 100644 .svn/pristine/5d/5df6cb671df6614fa95300a808373169e18b0950.svn-base
create mode 100644 .svn/pristine/5e/5e0f209f6e9be1f84238e9cb97288fda3cb63dd8.svn-base
create mode 100644 .svn/pristine/5e/5e69ecefe93f6f0a7f5115c7b8607aed51ee86b3.svn-base
create mode 100644 .svn/pristine/5e/5eefdb2ff77b3c733abee24187f2c857e1575160.svn-base
create mode 100644 .svn/pristine/5f/5f3c79403def080514a6099b44ebf7859d676dfa.svn-base
create mode 100644 .svn/pristine/60/6010f6e6b4ef4842fdf73cda2293b84c0a1a594e.svn-base
create mode 100644 .svn/pristine/60/60e222efc80001d9b4fd6ad73d8acf97f1791a12.svn-base
create mode 100644 .svn/pristine/61/618fd6a64917cdc9be9a1c4e95d8be9514c251bc.svn-base
create mode 100644 .svn/pristine/62/62cd714157ac917a85023be10ae67e3cb858fc36.svn-base
create mode 100644 .svn/pristine/63/63b5eeb5c16e41033bcb6a62a5b8f4381c1269d3.svn-base
create mode 100644 .svn/pristine/64/647fb4a8049def9bef1529c3cee8e41064f42398.svn-base
create mode 100644 .svn/pristine/64/64c8d30cc5e3ebe389ecf298872d498c1627b692.svn-base
create mode 100644 .svn/pristine/65/652413db7a8b435762332e2dca283ce69d621742.svn-base
create mode 100644 .svn/pristine/65/65e92da884776f00b5f5b2567d61c4e002873e42.svn-base
create mode 100644 .svn/pristine/66/6604ddf9fd99648487db8e77ab74a256057d05c1.svn-base
create mode 100644 .svn/pristine/66/662a6b769bb8e4a3354541002925d04ae2c67206.svn-base
create mode 100644 .svn/pristine/66/666fcb3bbce449bca217b7cf8f47597cb2e80b4c.svn-base
create mode 100644 .svn/pristine/66/66db365df3a0eef942cb42a5d2edf3b8aeccfa06.svn-base
create mode 100644 .svn/pristine/67/67c83eeb01bd32a29ffbb06e7d26923eb9e0b99f.svn-base
create mode 100644 .svn/pristine/68/684f85e901677b3d015a29e4a97842a54bf31b55.svn-base
create mode 100644 .svn/pristine/68/68aed022eff7b99141ac4f11df390f8472aed419.svn-base
create mode 100644 .svn/pristine/68/68d407e847706ef76e4ce91b3cb134f7cba7b934.svn-base
create mode 100644 .svn/pristine/69/6968d02e625c251705202b05c9c86db26f849ce0.svn-base
create mode 100644 .svn/pristine/69/69a3f8a76c536023aa70a4636340051de98f98f5.svn-base
create mode 100644 .svn/pristine/6a/6a6fad4475bfbd32efc844dcbb6477da14be104b.svn-base
create mode 100644 .svn/pristine/6a/6aa307a7e4996aeaff2750f6d1d29937beacf1a9.svn-base
create mode 100644 .svn/pristine/6b/6b7ee254db7c164592c699679747f995b2fc8873.svn-base
create mode 100644 .svn/pristine/6b/6be652e120b1822c2510bf2b96cddbeba44640e0.svn-base
create mode 100644 .svn/pristine/6d/6d3502f70c9b2dfadb1781397fce37a2913868a8.svn-base
create mode 100644 .svn/pristine/6d/6df93cb99c22899881828e41c73aedf42b01c556.svn-base
create mode 100644 .svn/pristine/6d/6dfacd2bb6de28bf6f10a6acbcec488fec3d1012.svn-base
create mode 100644 .svn/pristine/6e/6e381aa140910e9ec1132c16f86bcd1b3e49f281.svn-base
create mode 100644 .svn/pristine/6e/6ebe7159ab9c1af6a6eaa750ecc1a2608741f5c0.svn-base
create mode 100644 .svn/pristine/6f/6f022833514203e0e2ad638d675e7945aa45f504.svn-base
create mode 100644 .svn/pristine/6f/6f7cd87450d993408705a40f6c4c6f9b73b61e40.svn-base
create mode 100644 .svn/pristine/6f/6fa23b331596d4ca384380e02a63ef4865b44de0.svn-base
create mode 100644 .svn/pristine/6f/6fc6009546d91420a0e3443ed43eb1701600c23a.svn-base
create mode 100644 .svn/pristine/70/7070d0136318f52b3e73dbec82adcd0763b6070f.svn-base
create mode 100644 .svn/pristine/70/70871803b3f6bf0d01a81cd0dba737f90329d6d8.svn-base
create mode 100644 .svn/pristine/70/70b3ce496cd96d125a43029e9404b89170ade3f0.svn-base
create mode 100644 .svn/pristine/71/7120d417d78433f650b2d900e33537b2850405c6.svn-base
create mode 100644 .svn/pristine/71/7146719e63a7bb9a2d7ca1de86124879b983ab80.svn-base
create mode 100644 .svn/pristine/71/71586ace1d52f692154f322705a6637c1850da7c.svn-base
create mode 100644 .svn/pristine/71/71be27bff6dc7447697e0e88878aee8545ba6de6.svn-base
create mode 100644 .svn/pristine/71/71d3a41dbac37c4407fb1d7c8b8d533f0e3c5db3.svn-base
create mode 100644 .svn/pristine/71/71e30a24c656bce8aa2661657a925bc48f310ade.svn-base
create mode 100644 .svn/pristine/72/72dbeb2b4427453bd07542db3342d3bac1936571.svn-base
create mode 100644 .svn/pristine/73/73169ec498cfe5ae20b2c4041e07e09b7ca1f8e1.svn-base
create mode 100644 .svn/pristine/73/7368be85c075f0e6678f5c2b15e3922205cd47ee.svn-base
create mode 100644 .svn/pristine/74/74248ea87c8788dbd8b139458356324e132a4488.svn-base
create mode 100644 .svn/pristine/74/742f30c99049ecf6af01bcf74ba7a8e5e4e0afb1.svn-base
create mode 100644 .svn/pristine/74/7456163da0ca1fe6074ad84d3c847f9c7bf63726.svn-base
create mode 100644 .svn/pristine/75/75585ec6d7b36650e2fd6ba7c246c03aa2ba8eee.svn-base
create mode 100644 .svn/pristine/75/7561bf12879e32df7b13f342446694068da6889d.svn-base
create mode 100644 .svn/pristine/75/75c4d0cb7e7de819d001cc33ee69fd6adebc0c1f.svn-base
create mode 100644 .svn/pristine/75/75ef093ee88994ee7787a48be5857cecbb05c19a.svn-base
create mode 100644 .svn/pristine/76/769701ab5be5012cb834c3294f238aa09f8ed694.svn-base
create mode 100644 .svn/pristine/76/76a0ae6767782273553887125668d1ee84d4f646.svn-base
create mode 100644 .svn/pristine/77/77392d5c171ac5c4b573ca5862f14d15b0b6e1dd.svn-base
create mode 100644 .svn/pristine/77/77d350f9739d0187dc080c10c4a278eb975a9edd.svn-base
create mode 100644 .svn/pristine/78/78a88411e23055bcf5224ceccf7375d43fc958d5.svn-base
create mode 100644 .svn/pristine/78/78e14e399a2115c3bd270cbc79c827375577fa95.svn-base
create mode 100644 .svn/pristine/79/79478e7f48dc30040e033e21d4245206e1523445.svn-base
create mode 100644 .svn/pristine/79/795d6137bbfd5bbdca0eb0004d34288120bea1a8.svn-base
create mode 100644 .svn/pristine/79/79ec4ef5ce657255545a6a2946a1bce7ff20f8f5.svn-base
create mode 100644 .svn/pristine/7a/7a6c6df91775348234abd80a4f60c40470b0bca0.svn-base
create mode 100644 .svn/pristine/7a/7a9146e59d643aec9723d14b0032a28ff5ff1ccf.svn-base
create mode 100644 .svn/pristine/7b/7b5fd510b24a931070fc286efa8622d2037259d9.svn-base
create mode 100644 .svn/pristine/7b/7b92bc1d7aa4a712f94227106a3f15cfc054926e.svn-base
create mode 100644 .svn/pristine/7b/7b9989c725105ff9036724f89c5b79c473a903d2.svn-base
create mode 100644 .svn/pristine/7b/7bc31082bb482c2353076eae6992fa4742b18f9e.svn-base
create mode 100644 .svn/pristine/7c/7c5b5528a02fa42a59d2cdd1e4813287c903ba4b.svn-base
create mode 100644 .svn/pristine/7c/7c77142e1f39a71cf768fe2b76b65ec4b3ec66f9.svn-base
create mode 100644 .svn/pristine/7d/7d67785200c5e064d0a1548f0e289daadf7ef2b8.svn-base
create mode 100644 .svn/pristine/7f/7f161d58ca6f8b3d939693d960919c02ec6f8edd.svn-base
create mode 100644 .svn/pristine/7f/7f94cb4684a8f2323d841b58e5517303a5e2b37d.svn-base
create mode 100644 .svn/pristine/81/818e458d3f105d0edf6cdeaa093d587b1c9882bf.svn-base
create mode 100644 .svn/pristine/82/82e1450b4f791b928f4c564b112d1ae9f04c464f.svn-base
create mode 100644 .svn/pristine/83/839f7f89082e5a7d4306757bd4233b3e049cbfd2.svn-base
create mode 100644 .svn/pristine/84/841dc8550db01555b35793490e90ba2e09348ad5.svn-base
create mode 100644 .svn/pristine/84/84eaed9272c56a0aeb23f714c0b321ab8d037c66.svn-base
create mode 100644 .svn/pristine/85/8503fc37f9123c25db31aec5a6632fbf28ef03e6.svn-base
create mode 100644 .svn/pristine/85/855ce83a877fe9510bcb348627d52db70ebb70e6.svn-base
create mode 100644 .svn/pristine/85/8589c63ad52170308cdae2c6d5a64950f815cd4e.svn-base
create mode 100644 .svn/pristine/86/8640396e181ac4dcb2f45d4e70737b702328124d.svn-base
create mode 100644 .svn/pristine/86/8662ce73407a4f43552270d1d03fec78949097a5.svn-base
create mode 100644 .svn/pristine/87/87912ac2ce0b67b6d649e245ea13e17ffba40ab9.svn-base
create mode 100644 .svn/pristine/87/87c26523b0d60da1f3de24e50d2372552822372f.svn-base
create mode 100644 .svn/pristine/88/880f8b2789a7eb735412542d295753784c122a5c.svn-base
create mode 100644 .svn/pristine/88/889ac20cbaa0a1de1cb596d242e34c9a57e36007.svn-base
create mode 100644 .svn/pristine/88/88a49ab71d1b10febb41d27c82dfb6fe0aa531aa.svn-base
create mode 100644 .svn/pristine/88/88ac9c09c2ddf90e31b713a8b7cc90e8d2b87fe0.svn-base
create mode 100644 .svn/pristine/89/896f0f3d90929feaca46d59d98ee748639b617fe.svn-base
create mode 100644 .svn/pristine/89/8996d61e3ed3340138e2d205d61386137a224149.svn-base
create mode 100644 .svn/pristine/8a/8a3749dd4d20c589b00d8081b602a0a8f645396a.svn-base
create mode 100644 .svn/pristine/8a/8a9b899d45f3661b72ea781eee839c580872c6ba.svn-base
create mode 100644 .svn/pristine/8a/8abf2d01144747bd0f94d996b4042ef26f184531.svn-base
create mode 100644 .svn/pristine/8a/8acd94716d77465e773ffcf4c4aa1e3d4ed4bf12.svn-base
create mode 100644 .svn/pristine/8b/8b6c1024544679d71ce893276c3eeef5d398a410.svn-base
create mode 100644 .svn/pristine/8b/8bd6f70fb2155d3e78b896eab7c735e569f0b4af.svn-base
create mode 100644 .svn/pristine/8c/8c0a14cfe356fb9c0954d63499cb8198f3ea2c60.svn-base
create mode 100644 .svn/pristine/8c/8c243cee4874ad88b5459c4c59ae26b7d9648f15.svn-base
create mode 100644 .svn/pristine/8c/8c362c8854daad6cfdf50419e61fd334d0d69988.svn-base
create mode 100644 .svn/pristine/8d/8d0a1aaf21697a4fd06ac8def4685ee38fd87c88.svn-base
create mode 100644 .svn/pristine/8d/8d17d267f6e594883c5f95343cebb4be7d057a73.svn-base
create mode 100644 .svn/pristine/8d/8d8bf9d6a9d3c9170ddd1851e7d4781d8b7091b5.svn-base
create mode 100644 .svn/pristine/8e/8e2e4babd3ac4b211249bac4ad8fbf11a3173407.svn-base
create mode 100644 .svn/pristine/8e/8e45726aae25ace2bc1b2fee3a11dec614a65299.svn-base
create mode 100644 .svn/pristine/8e/8e47b886d7e8a79b22b92bebbfdbad4754e0cba2.svn-base
create mode 100644 .svn/pristine/8e/8e4d6a36cddbce2fb52c50f65c2debf471676f59.svn-base
create mode 100644 .svn/pristine/8e/8e536a862b62d4cdbe7e7560e0680c941dd3e6f7.svn-base
create mode 100644 .svn/pristine/8e/8ee802469d180eab8f04a6d5e672584ff2fc71ee.svn-base
create mode 100644 .svn/pristine/8f/8f7ba704a07d51f484a829817f9fb230eebd4d2f.svn-base
create mode 100644 .svn/pristine/90/9023dbdd9a3b9483b641cf7b63a2cde8c23cc467.svn-base
create mode 100644 .svn/pristine/90/909894694ae4f0b517aa97eb54df20067c2a200e.svn-base
create mode 100644 .svn/pristine/90/90eab1f264f76d12306f58d53b50a9bde3842980.svn-base
create mode 100644 .svn/pristine/90/90efa157a2c7cccae9b9407f3dad3177901ed128.svn-base
create mode 100644 .svn/pristine/91/914c6a441186ec3cb94e0f46a53375aaa0a2ac64.svn-base
create mode 100644 .svn/pristine/91/9188bcf7c01998cc21b4039aceb05c5357a120a9.svn-base
create mode 100644 .svn/pristine/91/9189532d7f4671f492f2b411c9c28342621a38d2.svn-base
create mode 100644 .svn/pristine/92/923b54b0faea32304a45a8bcf00535558167ab90.svn-base
create mode 100644 .svn/pristine/92/92717003914e684b39e38aaeefb04a3406a33e22.svn-base
create mode 100644 .svn/pristine/93/93b3e056f34f9675d1c724a0bd1275d58cffa242.svn-base
create mode 100644 .svn/pristine/93/93b9e144a97d9779f8bde4b20731baad9dd5059f.svn-base
create mode 100644 .svn/pristine/93/93d5c4d32db761185cc722e9e153c5bae1349942.svn-base
create mode 100644 .svn/pristine/95/9522ec8e06a343fd032c825b9db1a1624e030ce8.svn-base
create mode 100644 .svn/pristine/95/95d44030740705527e7ced9f8d11475f2e971383.svn-base
create mode 100644 .svn/pristine/97/977a31b0d51489403a4cac6a96125226175fcc51.svn-base
create mode 100644 .svn/pristine/97/9785d43d53a6967f418cdd5062899fe17a1aea4f.svn-base
create mode 100644 .svn/pristine/97/97f2ae1b2034911b23a4c9b55d33f68143b0a5f0.svn-base
create mode 100644 .svn/pristine/99/991138d5da7bf4ff94fe15d1c7a6915f9430cf80.svn-base
create mode 100644 .svn/pristine/99/99601644e074e097ac04ed7dda08f0314a984954.svn-base
create mode 100644 .svn/pristine/99/99a6b8318608fbddab0057aa349563bfce7a7b99.svn-base
create mode 100644 .svn/pristine/9a/9a558b4534c4600707bd5ac91e094e6098f20e10.svn-base
create mode 100644 .svn/pristine/9b/9b144ea0baa27d530f00f8bc55d17bed4dadc178.svn-base
create mode 100644 .svn/pristine/9b/9b45e5feb3ca22ca789a851abad4f0f2e3752fff.svn-base
create mode 100644 .svn/pristine/9b/9bd2d59eef8836e9f2f062d0faa1084595a9d830.svn-base
create mode 100644 .svn/pristine/9c/9c1b26c6cc14d90ec74f2fcffb87eaa278f758a5.svn-base
create mode 100644 .svn/pristine/9c/9c35576ff44b8980211e15c08927f4fca761e72d.svn-base
create mode 100644 .svn/pristine/9d/9d050a2af805f358843a21697ee0f9999835ab7c.svn-base
create mode 100644 .svn/pristine/9d/9d2e3b6b687ed242c05358e83cabd153e5f36bd8.svn-base
create mode 100644 .svn/pristine/9d/9d415c6bb762cb8967a6bac0b48cd060c974ea7c.svn-base
create mode 100644 .svn/pristine/9e/9e563f1e1196eea07a0574820445932b889b5e25.svn-base
create mode 100644 .svn/pristine/9e/9e70966859dda8123abb6ebb7033cd9de27746f8.svn-base
create mode 100644 .svn/pristine/9f/9f8f165a92925b68377688fd088b3ae90e735a55.svn-base
create mode 100644 .svn/pristine/9f/9fe14bf3807fe747509ff2e883dc9ed6c0ad471e.svn-base
create mode 100644 .svn/pristine/9f/9fe5996eb204228a5a9f75b93e8d663d005bbf12.svn-base
create mode 100644 .svn/pristine/a1/a129a3135d09a29263d98fd0741ed447bf11db8a.svn-base
create mode 100644 .svn/pristine/a1/a17f97cdf3eaad407eb158ecc0426db56e71fddd.svn-base
create mode 100644 .svn/pristine/a1/a195f222cd7927b51252f194d902a32b20d0fe0d.svn-base
create mode 100644 .svn/pristine/a2/a21b1d553de78d6f3dda34325fab38ba1461ecc8.svn-base
create mode 100644 .svn/pristine/a2/a2d38e8ca58ded60938f9f32370a01310427a7e6.svn-base
create mode 100644 .svn/pristine/a3/a3237121dd5fdf8b5da7a2f313157959e4b75735.svn-base
create mode 100644 .svn/pristine/a4/a40353e9eb2eb2a49098098c20b47fdff7bec7d0.svn-base
create mode 100644 .svn/pristine/a4/a4f3eded0950a8028f07005db4bca847e8b2ff95.svn-base
create mode 100644 .svn/pristine/a5/a547e94827ccfb6a37830953c902d64ea944cd8d.svn-base
create mode 100644 .svn/pristine/a5/a5c473d1c48212e9569a13bb6fc4715dbf015a46.svn-base
create mode 100644 .svn/pristine/a6/a60314806bae5b8a198e029cc0fc42e89d4ecd0d.svn-base
create mode 100644 .svn/pristine/a6/a69813b2320af21c84af18f310d7f35090521b2f.svn-base
create mode 100644 .svn/pristine/a6/a69f6204862af372410286012dfdf316971ab2e2.svn-base
create mode 100644 .svn/pristine/a6/a6c3a8c4a51bff8dcd3d668f7209549497209512.svn-base
create mode 100644 .svn/pristine/a6/a6c4c9528342b0a41b56a7c3115aace8b4c73c19.svn-base
create mode 100644 .svn/pristine/a8/a83cd5ad09cf59aa3349a43bb74edf81e509216e.svn-base
create mode 100644 .svn/pristine/a8/a845322f2fac8ace4b160c406372f0f0d77c2257.svn-base
create mode 100644 .svn/pristine/ab/ab7a8ced9853c6bb1976f4980b12660cf0d17d13.svn-base
create mode 100644 .svn/pristine/ab/ab7b473a8008a407abd8e92a84c02961f0c804e1.svn-base
create mode 100644 .svn/pristine/ab/abb490c481940ef81a0e404b4712f28a84606fd5.svn-base
create mode 100644 .svn/pristine/ac/ac07743845d2146d8b4fecf634872efd2b9946f7.svn-base
create mode 100644 .svn/pristine/ac/ac10a4c37fee7a051b4bfa4c915e446887dab965.svn-base
create mode 100644 .svn/pristine/ac/acf8f65c5f1ed377d2d86feefdb2ae4e58f79ee9.svn-base
create mode 100644 .svn/pristine/ad/ad1ba3e8c013ad723cb4f540e1e8d3a362122c22.svn-base
create mode 100644 .svn/pristine/ad/ad9f7f302d438b7ec230f1ec681796987b5423c1.svn-base
create mode 100644 .svn/pristine/ae/ae5555c2f61f8ed3375c6f7cb136bbd05f91a585.svn-base
create mode 100644 .svn/pristine/ae/ae7fd18a4d274761f39ea46bf56ea89a4998e837.svn-base
create mode 100644 .svn/pristine/af/afe401f366dc73e836372fed630c61d70eda4232.svn-base
create mode 100644 .svn/pristine/af/afee6bedacf1e2e20c98d8dc661db3fc0a82c587.svn-base
create mode 100644 .svn/pristine/b0/b01e2a83d07bca0b75930717f70befd11c03d7f5.svn-base
create mode 100644 .svn/pristine/b0/b0aeea527f1263e38bcb41b0a5b6c47ed2c03458.svn-base
create mode 100644 .svn/pristine/b0/b0cf49940cbd24a36f24bc9f716d97ff7948f7cc.svn-base
create mode 100644 .svn/pristine/b0/b0f5136c90fe93c16c19cf8a04906e3d230f1343.svn-base
create mode 100644 .svn/pristine/b1/b11be7a5f3f3e22c1f073bfafc11e8a1ff546a45.svn-base
create mode 100644 .svn/pristine/b2/b240dbba7d58a2d38a85548534b6a8bf9ebcd4d3.svn-base
create mode 100644 .svn/pristine/b3/b3bf74b403984a104f3ecd1cde3bc17717f3195d.svn-base
create mode 100644 .svn/pristine/b4/b423d23f684b407d0678b338394566e3fcfd9d42.svn-base
create mode 100644 .svn/pristine/b4/b42a02a41b8ec24f10cfd7ef2390993db053a5dd.svn-base
create mode 100644 .svn/pristine/b4/b49ae28bef57ca8c230881172effa82ec13a1328.svn-base
create mode 100644 .svn/pristine/b4/b4cd7d004e9f66700f2b19b73cca6358f845dbee.svn-base
create mode 100644 .svn/pristine/b5/b56a5df3e72cce3b15f78b80d2e01ae4e840ca42.svn-base
create mode 100644 .svn/pristine/b5/b575a6e7d282379be80340866ffec7e113d0be04.svn-base
create mode 100644 .svn/pristine/b6/b6109d1a9358a108e9893e6373d6367d7b5bd097.svn-base
create mode 100644 .svn/pristine/b6/b61b34daeef58db23ce230e72c479fd030f09049.svn-base
create mode 100644 .svn/pristine/b6/b63ba8b4a137f1d4a6420d607830ebf682565fb0.svn-base
create mode 100644 .svn/pristine/b6/b6679e26d8b08ff4deee86edabc68281eb2aa761.svn-base
create mode 100644 .svn/pristine/b6/b67c71ad6d4011208c23f5803e9b2d47e4741762.svn-base
create mode 100644 .svn/pristine/b7/b76c131fcc8988414e015573f923439a7d4c436d.svn-base
create mode 100644 .svn/pristine/b8/b89ae7c39b0d717a0740bde098aef421172931e0.svn-base
create mode 100644 .svn/pristine/b9/b91d52178b3aa8d56c652daf9e7392072a05089b.svn-base
create mode 100644 .svn/pristine/b9/b946a400b24ba35b977cec32e4b4a7a2a15f64fe.svn-base
create mode 100644 .svn/pristine/b9/b96f577140a96cce4d3b17e69da36c41ccec5d21.svn-base
create mode 100644 .svn/pristine/ba/ba240118a1bab462cda6e1cea30162e41d980fd6.svn-base
create mode 100644 .svn/pristine/ba/ba3c9bda125380ebd777853631dd19c39c833078.svn-base
create mode 100644 .svn/pristine/bb/bb3ad5934d171a294360c2c0b822b661307ecf5c.svn-base
create mode 100644 .svn/pristine/bb/bb649b8a5501aeab80fd26539cb17ed51d6e4385.svn-base
create mode 100644 .svn/pristine/bc/bc3b70d0e67d7c540ee994071895fcc82ea4a536.svn-base
create mode 100644 .svn/pristine/bc/bc522948666eab758050eec70b0bf011b787bd22.svn-base
create mode 100644 .svn/pristine/bc/bc9810801d5a04ec8892e50a9d1068234feb68b3.svn-base
create mode 100644 .svn/pristine/bd/bd98fb8ea7dd1c5f77fa37da94eba73aa4e8655a.svn-base
create mode 100644 .svn/pristine/be/be1bee5bab80c9061bc8c533bec08ed61313f245.svn-base
create mode 100644 .svn/pristine/be/be4c80b6a1cb2e70b9f49c5b60056a8f0c31e535.svn-base
create mode 100644 .svn/pristine/bf/bf8bed91ae6e4e864c464aeb7699d8ca58ca11ad.svn-base
create mode 100644 .svn/pristine/c0/c039b778dc27da0bcdd2b2ba3f68ccff92a08c4e.svn-base
create mode 100644 .svn/pristine/c0/c06bb00b275693322fe223e6bb21f68b387c664e.svn-base
create mode 100644 .svn/pristine/c0/c08ddfac5b0e55a5d280c01f5ba84175746c6670.svn-base
create mode 100644 .svn/pristine/c0/c091d4650a869c38d9df717b755882d3d4fba5da.svn-base
create mode 100644 .svn/pristine/c0/c0a839d663b36c1a3dd52beeaada9454b05cff52.svn-base
create mode 100644 .svn/pristine/c0/c0a920465d6c9834818864e94ce6e312aa2a67b7.svn-base
create mode 100644 .svn/pristine/c0/c0a9c398935ca0387070ea4a67edb3d619f2c52c.svn-base
create mode 100644 .svn/pristine/c0/c0efd300de5dd318956d73491271fff4d613b8f6.svn-base
create mode 100644 .svn/pristine/c1/c1002c3202fd344afff9a31caf97f8185a3a32b7.svn-base
create mode 100644 .svn/pristine/c1/c1886a33f03908ff2845be69750fc79cee39911b.svn-base
create mode 100644 .svn/pristine/c1/c1fb19bc50b27b5dcf3d3910d3cff5d33b44f849.svn-base
create mode 100644 .svn/pristine/c2/c2f333e8bb1fb13e5def7fe4f3e07ed2abf8d76e.svn-base
create mode 100644 .svn/pristine/c3/c326fb3a7fd2dfd1b789ed02f487f7403096c840.svn-base
create mode 100644 .svn/pristine/c3/c3c462d822110dcbf1f382143d5a877c61ec4fee.svn-base
create mode 100644 .svn/pristine/c4/c40eae5e252d7ed7287077f79b78b686a9b4aaa1.svn-base
create mode 100644 .svn/pristine/c4/c421f505cbaaada678e87728ca356f20a02116c0.svn-base
create mode 100644 .svn/pristine/c4/c42789cf369f7d04b4b020958f75e075db449ae7.svn-base
create mode 100644 .svn/pristine/c4/c491be48ac132bfc8b23390937e87d0c58902b52.svn-base
create mode 100644 .svn/pristine/c4/c4f4b943db5c43710acf7e60612fe72744ad4e20.svn-base
create mode 100644 .svn/pristine/c5/c5379f92820998bd3b2bb0a673fc1c4912af40ce.svn-base
create mode 100644 .svn/pristine/c5/c565a4d99aa51d1ef50a7b8d7b8100fcdbaf1ab7.svn-base
create mode 100644 .svn/pristine/c5/c57567ea0fe52dba7818253da9131d03d9481406.svn-base
create mode 100644 .svn/pristine/c5/c5d42b0c9ad46b1253e1ef181a719dd4776db3e9.svn-base
create mode 100644 .svn/pristine/c6/c68ab64d3b71584cf45c3ea68f9eef9d142db43a.svn-base
create mode 100644 .svn/pristine/c6/c6fd99ae25255a50bd65a58be00c99a345db66a6.svn-base
create mode 100644 .svn/pristine/c7/c74c80d14df9ce81e129eb39ba943cd52b901461.svn-base
create mode 100644 .svn/pristine/c7/c7630d863d95380821f9ede591b1d4edd50b1734.svn-base
create mode 100644 .svn/pristine/c8/c875e127d82fb46c705dd83275d7af5804b89e72.svn-base
create mode 100644 .svn/pristine/c8/c8cc14965d0ac04fe19f8233d9823f57230d2751.svn-base
create mode 100644 .svn/pristine/c9/c995728eecabcbf96383384d641b5ac70af2d741.svn-base
create mode 100644 .svn/pristine/ca/ca19e21faa71fb1b5a78c6b29cb7eeacc9d946ca.svn-base
create mode 100644 .svn/pristine/ca/ca3f42bd2212fed985f763417899f7d027bd7624.svn-base
create mode 100644 .svn/pristine/ca/ca7b957fe9a5631e1775ae3148f392bcecf9810d.svn-base
create mode 100644 .svn/pristine/ca/cac300511b92e329a4c7f42a1a4482984549452e.svn-base
create mode 100644 .svn/pristine/cb/cb2dc1cc84883eae776ffcd5c34f7d2287d1d64e.svn-base
create mode 100644 .svn/pristine/cb/cb55eb4e6f73afb74314ae96ea02d60873a3924b.svn-base
create mode 100644 .svn/pristine/cc/cc26cf9c9870e83ca5586e5fcc655f5e598bf056.svn-base
create mode 100644 .svn/pristine/cc/cc7b87da2822815af226fced2f1ea3ed0bdce14d.svn-base
create mode 100644 .svn/pristine/ce/ce2de3130718fd2af4d75e902ed17e43f4d4a7a3.svn-base
create mode 100644 .svn/pristine/ce/ce4a3f5ce85954f7658922149992c41f561dff23.svn-base
create mode 100644 .svn/pristine/ce/ceddbb1b8e59b7257438ac43b697595693ed67ad.svn-base
create mode 100644 .svn/pristine/cf/cf185e56d8fd912e9e92a03b65f428d6c1ca67a8.svn-base
create mode 100644 .svn/pristine/cf/cf8c6d8f936336e6b1980b10b3e3a1c5b25cf979.svn-base
create mode 100644 .svn/pristine/cf/cfd993e86fa908f28c65e99fb9244f7215732d3a.svn-base
create mode 100644 .svn/pristine/d0/d0734fe3356e109ca02d690a0f3e112c1b7160a9.svn-base
create mode 100644 .svn/pristine/d0/d0cc2247e38dcb58a637660153d0975bc1a12435.svn-base
create mode 100644 .svn/pristine/d0/d0f551cb09dd6913b8db7aa1101567e654d5688b.svn-base
create mode 100644 .svn/pristine/d1/d13ac46b10658b7f1d9a676fb7ac48039ce5811d.svn-base
create mode 100644 .svn/pristine/d1/d1f6e89e4dd7928626cfb64f2aa60c02f20b3377.svn-base
create mode 100644 .svn/pristine/d2/d222c1e95ba289f2814d142867f8b3c8b656bcc6.svn-base
create mode 100644 .svn/pristine/d2/d2bd8ef5b2dc0b67c16cc0ca0969ccc3beced3b5.svn-base
create mode 100644 .svn/pristine/d3/d33fd910f90ddc71ac1e55d805509de083160973.svn-base
create mode 100644 .svn/pristine/d3/d35e70599f309c79bfe065f74852ad8472550a64.svn-base
create mode 100644 .svn/pristine/d4/d41d37abdf356528e88b81a4d056ef101c3f2dab.svn-base
create mode 100644 .svn/pristine/d4/d4dab9d46311ec1a7fb33f7af3bf321e12849b3e.svn-base
create mode 100644 .svn/pristine/d5/d53db9bb77af890ae642df0aa8057fec9c270362.svn-base
create mode 100644 .svn/pristine/d6/d632d9ab9323a898bdd54e298af7d72c23e17c92.svn-base
create mode 100644 .svn/pristine/d6/d6a8214b84435287bed433151d37fdb4ea278134.svn-base
create mode 100644 .svn/pristine/d6/d6b67ac69f06a10e8753aa29615c830eeb6a93d2.svn-base
create mode 100644 .svn/pristine/d6/d6ec0a4bd1c8f91e144ffc3eccd5771e0106b89e.svn-base
create mode 100644 .svn/pristine/d6/d6f3c843ced3bcd5ef55db9e89d8f8ec57c08169.svn-base
create mode 100644 .svn/pristine/d7/d7fe58b799b68f61c0ca2c70c53a76bf8682d53d.svn-base
create mode 100644 .svn/pristine/d8/d85a410b3f753b8db98c4342a8078aa3838834fa.svn-base
create mode 100644 .svn/pristine/d9/d911723cb0a99dea745caf06399d529660b36d78.svn-base
create mode 100644 .svn/pristine/d9/d943a8e9bea8c3724f745fe7d08fa08a881f29fe.svn-base
create mode 100644 .svn/pristine/d9/d97f73cc9aa74a9ffcb94751abbf611552780c8f.svn-base
create mode 100644 .svn/pristine/da/da0127ddf0fa01fadb0e50628107f55f6ea1526a.svn-base
create mode 100644 .svn/pristine/da/dabc4847f38c81b56214f92f20e124e9ca1b93d4.svn-base
create mode 100644 .svn/pristine/da/dac72da76990d5ed98122019a852685bff9ecba1.svn-base
create mode 100644 .svn/pristine/db/db1dfeaa1c83992313b5e816175c43d5072d5678.svn-base
create mode 100644 .svn/pristine/db/dbab0e101582adb9354ba950e8d577cc223c2bea.svn-base
create mode 100644 .svn/pristine/db/dbd36c0b2ae73296a480cbab67c3ac8aea40cd6b.svn-base
create mode 100644 .svn/pristine/dc/dc57f91be57c23e1a91c62285e300272fd3623cd.svn-base
create mode 100644 .svn/pristine/dc/dcc89f1e0718beb6b5b49feaa529021829d3b47f.svn-base
create mode 100644 .svn/pristine/dc/dcdb89bfd04f2898b7d2946a2cf44f982d178eb7.svn-base
create mode 100644 .svn/pristine/de/de124d140239ce29e87a077e64aa7c8159a3e928.svn-base
create mode 100644 .svn/pristine/de/de61b853e7fb2a59f42cc32977cb9631c6a7c263.svn-base
create mode 100644 .svn/pristine/de/de81f9e5304752f27eb7b181c9c77a076688d4bd.svn-base
create mode 100644 .svn/pristine/de/dec54cf9336a04d99116d54ff6266e992cf946cf.svn-base
create mode 100644 .svn/pristine/df/df87342987b43f6444bb495946acb79428262a05.svn-base
create mode 100644 .svn/pristine/e0/e06e3f8f9a5b15112cc04add9c28694ac015a8be.svn-base
create mode 100644 .svn/pristine/e0/e0cf7caf16d11b427605727055ca0a7388f3220f.svn-base
create mode 100644 .svn/pristine/e1/e19e942176794c6dc0a3cb9beb67c4b0066f0ffe.svn-base
create mode 100644 .svn/pristine/e2/e24fe6d6c0f56252d82165dbd9b637f5e8f975a3.svn-base
create mode 100644 .svn/pristine/e2/e2ec4f515a45eb0ccc276f8fa20041907e256405.svn-base
create mode 100644 .svn/pristine/e5/e599f03582163ba6b008a2abcbdea0fc2dc8a0c3.svn-base
create mode 100644 .svn/pristine/e5/e5b7c5dfd5b278c287ae9d197d983f51fbdc15ac.svn-base
create mode 100644 .svn/pristine/e5/e5f2da69627ec9f1cca305600e859c660e059155.svn-base
create mode 100644 .svn/pristine/e6/e64d877b910200a3316573e71c62be3a379935e7.svn-base
create mode 100644 .svn/pristine/e6/e66a0722abcc4bff624523c02c220ea0387d4b9e.svn-base
create mode 100644 .svn/pristine/e6/e69f438416943da022b6cf12f3f0251b1236ed3b.svn-base
create mode 100644 .svn/pristine/e6/e6aba542f29b11c85b630929fef7c82b0ab1197a.svn-base
create mode 100644 .svn/pristine/e6/e6b5542cb6580dd798aadb4c3676c4966ca070a8.svn-base
create mode 100644 .svn/pristine/e6/e6ce29ec85ceea072453a3db80d7c58e973d4d5d.svn-base
create mode 100644 .svn/pristine/e6/e6f6fd71b6d39cbb78fdddd103eede2ab2a89718.svn-base
create mode 100644 .svn/pristine/e7/e7105cd6d80645a60d647632b7716ea9b6d69ddb.svn-base
create mode 100644 .svn/pristine/e7/e71529e46569f6a969f86e42624dcbffa80a4f16.svn-base
create mode 100644 .svn/pristine/e7/e796c92f40fa2604d8db9e96c1083d511736415d.svn-base
create mode 100644 .svn/pristine/e7/e7b8cf592043dfc9080641288182ff8e6fd6d49e.svn-base
create mode 100644 .svn/pristine/e7/e7f88ad23f8ac6c06f378c7cdade8f9337369d80.svn-base
create mode 100644 .svn/pristine/e9/e91405a486579bf0f1959fd5de612ce9e97ae022.svn-base
create mode 100644 .svn/pristine/e9/e923dec9d9d70dfd78901ecb2dbbded614afd0e8.svn-base
create mode 100644 .svn/pristine/e9/e95df60529b193cf39dd8b46dd9a6f7ef966e58b.svn-base
create mode 100644 .svn/pristine/e9/e96bd4fe1e6a2ec8e057e55d8ee429331f287ad8.svn-base
create mode 100644 .svn/pristine/e9/e9a25c16407252911a87b272f7f64f497d17542b.svn-base
create mode 100644 .svn/pristine/ea/eaf7c0a9c2313a6abe2a388f97c0cb700658ce2d.svn-base
create mode 100644 .svn/pristine/eb/ebc6fb7b64902191465d27dc97c32019918ed5b9.svn-base
create mode 100644 .svn/pristine/eb/ebde67d62cbb4d1bb07d1f0370afa81623f393ec.svn-base
create mode 100644 .svn/pristine/ec/ec041b29985e3681afcb3eaa56dda606f6e0d51f.svn-base
create mode 100644 .svn/pristine/ec/ec05d54506065c9c112ebd441d0cfaa4f4a85134.svn-base
create mode 100644 .svn/pristine/ec/ec17130c5b0f9db52ddd0cfc5ff557e651b936fc.svn-base
create mode 100644 .svn/pristine/ec/ec2292a314f67cb894878b7b487f342851d79a87.svn-base
create mode 100644 .svn/pristine/ec/ec5bedfc1bd3688d4378ddef823babd3dfb0e02e.svn-base
create mode 100644 .svn/pristine/ed/ed3b78e12ad648d170eb11a43db7c28fdd223a1c.svn-base
create mode 100644 .svn/pristine/ed/ed5143e802d0730e9010a072b97492835824bb93.svn-base
create mode 100644 .svn/pristine/ed/ed6433dbf60b75d8ef6d0279591a1e26fcd8f164.svn-base
create mode 100644 .svn/pristine/ef/ef00ceddabaa27bdbb76e57d2a73f9d947cd1db5.svn-base
create mode 100644 .svn/pristine/f0/f0ba0fc390b73dc27ebd1a445e6c10f3ec070506.svn-base
create mode 100644 .svn/pristine/f1/f10cbb90e294528fae314f41e36b5e80aa5ce77c.svn-base
create mode 100644 .svn/pristine/f1/f11e1a9808888c4657fd023c4a36410c8bda7642.svn-base
create mode 100644 .svn/pristine/f1/f121e5bedc77f15ddf9b33e6141080c2cfa6a8ee.svn-base
create mode 100644 .svn/pristine/f1/f1b56bc707c94e31ef151838b9aa2d41b9738b29.svn-base
create mode 100644 .svn/pristine/f2/f220dfda26094cfbbd7697f23ff12b8a8296034c.svn-base
create mode 100644 .svn/pristine/f3/f318c68e9812e4e8a225bda8fbbb01b98335b5d6.svn-base
create mode 100644 .svn/pristine/f3/f34b44fe2be2bf84ef422f6d46fee1c6d72927db.svn-base
create mode 100644 .svn/pristine/f3/f3c279eeb223e05c1256bc2d323cfa1d3defaf89.svn-base
create mode 100644 .svn/pristine/f4/f4e0fde8ad5651d411a686ad381c517573db21e9.svn-base
create mode 100644 .svn/pristine/f5/f58250803d3356b5564ba6e3a702f2c4e7fb91bd.svn-base
create mode 100644 .svn/pristine/f6/f69ea72a6e4869e6ce75ae57cbae6ff30fb992bf.svn-base
create mode 100644 .svn/pristine/f6/f6f0135384da66767c5365f798b9e8c45711d2c8.svn-base
create mode 100644 .svn/pristine/f8/f8fa1a479a1db7242bd91c78fe029c7589d017a8.svn-base
create mode 100644 .svn/pristine/f9/f981ab7e084ceb657f0c2ad3d71422f9542bfd3d.svn-base
create mode 100644 .svn/pristine/fb/fb4c9ba7317ad7ed1c9f5de6c68d30046dbe55a3.svn-base
create mode 100644 .svn/pristine/fb/fba5d865596baf09e485ec88b49dd9fe9be838b4.svn-base
create mode 100644 .svn/pristine/fb/fbcb80dd06fa9acd7a21cd0f9af3886cf09c04f7.svn-base
create mode 100644 .svn/pristine/fc/fc031a75fb0107cbcac5a7bba48946987c1b1f89.svn-base
create mode 100644 .svn/pristine/fd/fd092548e659091bf86505b20ee145ef9b4e5a6a.svn-base
create mode 100644 .svn/pristine/fe/fe17ccb6deb51ba979ae080f7e5fa558450d24d6.svn-base
create mode 100644 .svn/pristine/ff/ff6ef4cb191804d9f0d6a4d12eb7e1bd38aa042d.svn-base
create mode 100644 .svn/pristine/ff/ff732541087a770c4b322620f99a90f745126be9.svn-base
create mode 100644 .svn/pristine/ff/fffdb9b3c6fd7a857bc59bde7d5bccea47d2020f.svn-base
create mode 100644 .svn/wc.db
create mode 100644 .svn/wc.db-journal
diff --git a/.idea/goProject.iml b/.idea/goProject.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/goProject.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..3c2fb49
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..b1c9cc9
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/.svn/entries b/.svn/entries
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/.svn/format b/.svn/format
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/.svn/pristine/00/001ae31cf129372b636ccad5355eca7cd5992f37.svn-base b/.svn/pristine/00/001ae31cf129372b636ccad5355eca7cd5992f37.svn-base
new file mode 100644
index 0000000..0d781a3
--- /dev/null
+++ b/.svn/pristine/00/001ae31cf129372b636ccad5355eca7cd5992f37.svn-base
@@ -0,0 +1,34 @@
+package webServer
+
+import (
+ "reflect"
+)
+
+// methodAndInOutTypes
+// @description: 反射的方法和输入、输出参数类型组合类型
+type methodAndInOutTypes struct {
+ // 反射出来的对应方法对象
+ Method reflect.Value
+
+ // 反射出来的方法的输入参数的类型集合
+ InTypes []reflect.Type
+
+ // 反射出来的方法的输出参数的类型集合
+ OutTypes []reflect.Type
+}
+
+// newmethodAndInOutTypes
+// @description: newmethodAndInOutTypes
+// parameter:
+// @_method: _method
+// @_inTypes: _inTypes
+// @_outTypes: _outTypes
+// return:
+// @*methodAndInOutTypes: methodAndInOutTypes
+func newmethodAndInOutTypes(_method reflect.Value, _inTypes []reflect.Type, _outTypes []reflect.Type) *methodAndInOutTypes {
+ return &methodAndInOutTypes{
+ Method: _method,
+ InTypes: _inTypes,
+ OutTypes: _outTypes,
+ }
+}
diff --git a/.svn/pristine/00/00274e716eefcbc7222fcf148fae2d4a027038d1.svn-base b/.svn/pristine/00/00274e716eefcbc7222fcf148fae2d4a027038d1.svn-base
new file mode 100644
index 0000000..59af09c
--- /dev/null
+++ b/.svn/pristine/00/00274e716eefcbc7222fcf148fae2d4a027038d1.svn-base
@@ -0,0 +1,110 @@
+gxpath
+====
+gxpath is XPath packages for the Go, that lets you extract data from the custom documents using XPath expression.
+
+**[XQuery](https://github.com/antchfx/xquery)** : gxpath implemented, lets you extract data from HTML/XML documents using XPath.
+
+### Features
+
+#### The basic XPath patterns.
+
+> The basic XPath patterns cover 90% of the cases that most stylesheets will need.
+
+- `node` : Selects all child elements with nodeName of node.
+
+- `*` : Selects all child elements.
+
+- `@attr` : Selects the attribute attr.
+
+- `@*` : Selects all attributes.
+
+- `node()` : Matches an org.w3c.dom.Node.
+
+- `text()` : Matches a org.w3c.dom.Text node.
+
+- `comment()` : Matches a comment.
+
+- `.` : Selects the current node.
+
+- `..` : Selects the parent of current node.
+
+- `/` : Selects the document node.
+
+- `a[expr]` : Select only those nodes matching a which also satisfy the expression expr.
+
+- `a[n]` : Selects the nth matching node matching a When a filter's expression is a number, XPath selects based on position.
+
+- `a/b` : For each node matching a, add the nodes matching b to the result.
+
+- `a//b` : For each node matching a, add the descendant nodes matching b to the result.
+
+- `//b` : Returns elements in the entire document matching b.
+
+- `a|b` : All nodes matching a or b.
+
+#### Node Axes
+
+- `child::*` : The child axis selects children of the current node.
+
+- `descendant::*` : The descendant axis selects descendants of the current node. It is equivalent to '//'.
+
+- `descendant-or-self::*` : Selects descendants including the current node.
+
+- `attribute::*` : Selects attributes of the current element. It is equivalent to @*
+
+- `following-sibling::*` : Selects nodes after the current node.
+
+- `preceding-sibling::*` : Selects nodes before the current node.
+
+- `following::*` : Selects the first matching node following in document order, excluding descendants.
+
+- `preceding::*` : Selects the first matching node preceding in document order, excluding ancestors.
+
+- `parent::*` : Selects the parent if it matches. The '..' pattern from the core is equivalent to 'parent::node()'.
+
+- `ancestor::*` : Selects matching ancestors.
+
+- `ancestor-or-self::*` : Selects ancestors including the current node.
+
+- `self::*` : Selects the current node. '.' is equivalent to 'self::node()'.
+
+#### Expressions
+
+ The gxpath supported three types: number, boolean, string.
+
+- `path` : Selects nodes based on the path.
+
+- `a = b` : Standard comparisons.
+
+ * a = b True if a equals b.
+ * a != b True if a is not equal to b.
+ * a < b True if a is less than b.
+ * a <= b True if a is less than or equal to b.
+ * a > b True if a is greater than b.
+ * a >= b True if a is greater than or equal to b.
+
+- `a + b` : Arithmetic expressions.
+
+ * `- a` Unary minus
+ * a + b Add
+ * a - b Substract
+ * a * b Multiply
+ * a div b Divide
+ * a mod b Floating point mod, like Java.
+
+- `(expr)` : Parenthesized expressions.
+
+- `fun(arg1, ..., argn)` : Function calls.
+
+ * position()
+ * last()
+ * count(node-set)
+ * name()
+ * starts-with(string,string)
+ * normalize-space(string)
+ * substring(string,start[,length])
+ * come more
+
+- `a or b` : Boolean or.
+
+- `a and b` : Boolean and.
diff --git a/.svn/pristine/00/0096b6776a09918ae8e11a6ea4ea0baebb972248.svn-base b/.svn/pristine/00/0096b6776a09918ae8e11a6ea4ea0baebb972248.svn-base
new file mode 100644
index 0000000..b5425d1
--- /dev/null
+++ b/.svn/pristine/00/0096b6776a09918ae8e11a6ea4ea0baebb972248.svn-base
@@ -0,0 +1,29 @@
+package ensureSendUtil
+
+/*
+ensureSendUtil 用于推送数据
+支持TCP和HTTP两种形式,在发送失败时会缓存数据,并在一定时间间隔后重试
+
+通过NewTCPSender和NewHTTPSender两个接口分别创建TCP和HTTP模式的EnsureSender
+
+type EnsureSender interface {
+ // 用于发送数据
+ Write(string) error
+
+ // 用于停止发送,此时会自动保存未发送数据
+ Close() error
+}
+
+// 创建一个tcp数据发送器
+// 参数:
+// _dataFolder 数据存放目录
+// _address 连接地址
+func NewTCPSender(_dataFolder, _address string) (EnsureSender, error) {
+
+
+// 创建一个http数据发送器
+// 参数:
+// _dataFolder 数据存放目录
+// _url 发送地址
+func NewHTTPSender(_dataFolder, _url string) (EnsureSender, error) {
+*/
diff --git a/.svn/pristine/01/01089319b44c6f1155fa6d3b8d81d7557fdea2a1.svn-base b/.svn/pristine/01/01089319b44c6f1155fa6d3b8d81d7557fdea2a1.svn-base
new file mode 100644
index 0000000..e274a21
--- /dev/null
+++ b/.svn/pristine/01/01089319b44c6f1155fa6d3b8d81d7557fdea2a1.svn-base
@@ -0,0 +1,129 @@
+/*
+url的格式如下:https://cmq-{$type}-{$region}.api.{$network}.com
+其最终内容受到以下因素的影响:地域、网络、消息队列模型
+
+地域
+gz(广州)、sh(上海)、bj(北京)、shjr(上海金融)、szjr(深圳金融)、hk(中国香港)、cd(成都)、ca(北美)、usw(美西)、use(美东)、in(印度)、th(泰国)、sg(新加坡)
+
+网络
+外网接口请求域名后缀:api.qcloud.com
+内网接口请求域名后缀:api.tencentyun.com
+
+队列模型
+请参照下面说明将域名中的 {$region} 替换成相应地域:
+外网接口请求域名:https://cmq-queue-{$region}.api.qcloud.com
+内网接口请求域名:http://cmq-queue-{$region}.api.tencentyun.com
+
+主题模型
+请参照下面说明将域名中的 {$region} 替换成相应地域:
+外网接口请求域名:https://cmq-topic-{$region}.api.qcloud.com
+内网接口请求域名:http://cmq-topic-{$region}.api.tencentyun.com
+*/
+package mqMgr
+
+import (
+ "fmt"
+ "strings"
+
+ "goutil/securityUtil"
+ "goutil/stringUtil"
+ "goutil/webUtil"
+)
+
+func getPrefix(network string) string {
+ if network == MQ_NETWORK_INTERNAL {
+ return "http://"
+ }
+
+ return "https://"
+}
+
+// // 获取请求url
+// // region:地域
+// // network:网络类型:内网、外网
+// // _type:消息队列类型:消息队列、消息主题
+// // 返回:
+// // 请求url
+// func getHost(region, network, _type string) string {
+// url := "cmq-{$type}-{$region}.api.{$network}.com"
+// url = strings.Replace(url, "{$region}", region, 1)
+// url = strings.Replace(url, "{$network}", network, 1)
+// url = strings.Replace(url, "{$type}", _type, 1)
+
+// return url
+// }
+
+// 获取请求url todo:切换成tdmq之后需要用这个方法
+// region:地域
+// network:网络类型:内网、外网
+// _type:消息队列类型:消息队列、消息主题
+// 返回:
+// 请求url
+func getHost(region, network, _type string) string {
+ var url string = ""
+ if network == MQ_NETWORK_INTERNAL {
+ url = "{$region}.mqadapter.cmq.{$network}.com"
+ } else {
+ url = "cmq-{$region}.public.{$network}.com"
+ }
+
+ url = strings.Replace(url, "{$region}", region, 1)
+ url = strings.Replace(url, "{$network}", network, 1)
+
+ return url
+}
+
+func getPath() string {
+ return "/v2/index.php"
+}
+
+func getMethod() string {
+ return "POST"
+}
+
+// AssembleUrl 组装请求url
+// 参数
+// region:地域
+// network:网络类型:内网、外网
+// _type:消息队列类型:消息队列、消息主题
+// secretKey:密钥的key
+// paramMap:参数字典
+// 返回值
+// string:组装好的请求url
+// string:签名
+// error:错误
+func AssembleUrl(region, network, _type, secretKey string, paramMap map[string]string) (url, signature string, err error) {
+ // 1. 申请安全凭证(已经得到)
+
+ // 2. 生成签名串
+ // 2.1、对参数排序
+ // 2.2、拼接请求字符串
+ // 注意:
+ // “参数值”为原始值而非 url 编码后的值。
+ // 若输入参数中包含下划线,则需要将其转换为“.”。(指的是参数的名称,不是参数的值)
+ paramStr := webUtil.AssembleRequestParamSort(paramMap, true)
+
+ // 2.3、拼接签名原文字符串
+ host := getHost(region, network, _type)
+ path := getPath()
+ signatureSource := fmt.Sprintf("%s%s%s?%s", getMethod(), host, path, paramStr)
+
+ // 2.4、生成签名串
+ data, err := securityUtil.HmacSha256(signatureSource, secretKey)
+ if err != nil {
+ return
+ }
+ signature = string(stringUtil.Base64Encode2(data))
+
+ // 3. 签名串编码
+ // 注意:
+ // 生成的签名串并不能直接作为请求参数,需要对其进行 URL 编码。
+ // 如果用户的请求方法是 GET,则对所有请求参数值均需要做 URL 编码。
+ // 如果是POST,则不用进行URL编码
+ // signature = url.QueryEscape(signature)
+
+ // 将签名添加到参数集合中
+ url = fmt.Sprintf("%s%s%s", getPrefix(network), host, path)
+
+ return
+}
diff --git a/.svn/pristine/01/010cd221ec8c3741fb44e0c141d45af65b1dcf19.svn-base b/.svn/pristine/01/010cd221ec8c3741fb44e0c141d45af65b1dcf19.svn-base
new file mode 100644
index 0000000..bf69716
--- /dev/null
+++ b/.svn/pristine/01/010cd221ec8c3741fb44e0c141d45af65b1dcf19.svn-base
@@ -0,0 +1,36 @@
+package timeUtil
+
+import (
+ "testing"
+ "time"
+)
+
+func TestGetTime(t *testing.T) {
+ timeVal := time.Date(2018, 4, 25, 9, 36, 1, 0, time.Local)
+ timeStr1 := ToDateTimeString2(timeVal)
+
+ utcTime := GetUTCTime(timeVal)
+ timeStr2 := ToDateTimeString2(utcTime)
+
+ if timeStr1 != timeStr2 {
+ t.Errorf("获取UTC时间出错,两个时间不对等")
+ }
+
+ utcTime2 := GetUTCTime(utcTime)
+ timeStr3 := ToDateTimeString2(utcTime2)
+ if timeStr1 != timeStr3 {
+ t.Errorf("两次的UTC时间不对等")
+ }
+
+ utcTime4 := GetLocalTime(utcTime)
+ timeStr4 := ToDateTimeString2(utcTime4)
+ if timeStr4 != timeStr1 {
+ t.Errorf("local变更了时间 time1:%v time4:%v", timeStr1, timeStr4)
+ }
+
+ utcTime5 := GetLocalTime(utcTime)
+ timeStr5 := ToDateTimeString2(utcTime5)
+ if timeStr4 != timeStr5 {
+ t.Errorf("两次的local时间不对等")
+ }
+}
diff --git a/.svn/pristine/01/013419d9030f7fb4c2de649a85be0862d57334ba.svn-base b/.svn/pristine/01/013419d9030f7fb4c2de649a85be0862d57334ba.svn-base
new file mode 100644
index 0000000..29de99f
--- /dev/null
+++ b/.svn/pristine/01/013419d9030f7fb4c2de649a85be0862d57334ba.svn-base
@@ -0,0 +1,658 @@
+package query
+
+import (
+ "reflect"
+
+ "goutil/xmlUtil/gxpath/xpath"
+)
+
+// An XPath query interface.
+type Query interface {
+ // Select traversing Iterator returns a query matched node xpath.NodeNavigator.
+ Select(Iterator) xpath.NodeNavigator
+
+ // Evaluate evaluates query and returns values of the current query.
+ Evaluate(Iterator) interface{}
+
+ // Test checks a specified xpath.NodeNavigator can passed by the current query.
+ //Test(xpath.NodeNavigator) bool
+}
+
+// ContextQuery is returns current node on the Iterator object query.
+type ContextQuery struct {
+ count int
+ Root bool // Moving to root-level node in the current context Iterator.
+}
+
+func (c *ContextQuery) Select(t Iterator) (n xpath.NodeNavigator) {
+ if c.count == 0 {
+ c.count++
+ n = t.Current().Copy()
+ if c.Root {
+ n.MoveToRoot()
+ }
+ }
+ return n
+}
+
+func (c *ContextQuery) Evaluate(Iterator) interface{} {
+ c.count = 0
+ return c
+}
+
+// AncestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*)
+type AncestorQuery struct {
+ iterator func() xpath.NodeNavigator
+
+ Self bool
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (a *AncestorQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if a.iterator == nil {
+ node := a.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ first := true
+ a.iterator = func() xpath.NodeNavigator {
+ if first && a.Self {
+ first = false
+ if a.Predicate(node) {
+ return node
+ }
+ }
+ for node.MoveToParent() {
+ if !a.Predicate(node) {
+ break
+ }
+ return node
+ }
+ return nil
+ }
+ }
+
+ if node := a.iterator(); node != nil {
+ return node
+ }
+ a.iterator = nil
+ }
+}
+
+func (a *AncestorQuery) Evaluate(t Iterator) interface{} {
+ a.Input.Evaluate(t)
+ return a
+}
+
+func (a *AncestorQuery) Test(n xpath.NodeNavigator) bool {
+ return a.Predicate(n)
+}
+
+// AttributeQuery is an XPath attribute node query.(@*)
+type AttributeQuery struct {
+ iterator func() xpath.NodeNavigator
+
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (a *AttributeQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if a.iterator == nil {
+ node := a.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ a.iterator = func() xpath.NodeNavigator {
+ for {
+ onAttr := node.MoveToNextAttribute()
+ if !onAttr {
+ return nil
+ }
+ if a.Predicate(node) {
+ return node
+ }
+ }
+ }
+ }
+
+ if node := a.iterator(); node != nil {
+ return node
+ }
+ a.iterator = nil
+ }
+}
+
+func (a *AttributeQuery) Evaluate(t Iterator) interface{} {
+ a.Input.Evaluate(t)
+ a.iterator = nil
+ return a
+}
+
+func (a *AttributeQuery) Test(n xpath.NodeNavigator) bool {
+ return a.Predicate(n)
+}
+
+// ChildQuery is an XPath child node query.(child::*)
+type ChildQuery struct {
+ posit int
+ iterator func() xpath.NodeNavigator
+
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (c *ChildQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if c.iterator == nil {
+ c.posit = 0
+ node := c.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ first := true
+ c.iterator = func() xpath.NodeNavigator {
+ for {
+ if (first && !node.MoveToChild()) || (!first && !node.MoveToNext()) {
+ return nil
+ }
+ first = false
+ if c.Predicate(node) {
+ return node
+ }
+ }
+ }
+ }
+
+ if node := c.iterator(); node != nil {
+ c.posit++
+ return node
+ }
+ c.iterator = nil
+ }
+}
+
+func (c *ChildQuery) Evaluate(t Iterator) interface{} {
+ c.Input.Evaluate(t)
+ c.iterator = nil
+ return c
+}
+
+func (c *ChildQuery) Test(n xpath.NodeNavigator) bool {
+ return c.Predicate(n)
+}
+
+// position returns a position of current xpath.NodeNavigator.
+func (c *ChildQuery) position() int {
+ return c.posit
+}
+
+// DescendantQuery is an XPath descendant node query.(descendant::* | descendant-or-self::*)
+type DescendantQuery struct {
+ iterator func() xpath.NodeNavigator
+
+ Self bool
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (d *DescendantQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if d.iterator == nil {
+ node := d.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ level := 0
+ first := true
+ d.iterator = func() xpath.NodeNavigator {
+ if first && d.Self {
+ first = false
+ if d.Predicate(node) {
+ return node
+ }
+ }
+
+ for {
+ if node.MoveToChild() {
+ level++
+ } else {
+ for {
+ if level == 0 {
+ return nil
+ }
+ if node.MoveToNext() {
+ break
+ }
+ node.MoveToParent()
+ level--
+ }
+ }
+ if d.Predicate(node) {
+ return node
+ }
+ }
+ }
+ }
+
+ if node := d.iterator(); node != nil {
+ return node
+ }
+ d.iterator = nil
+ }
+}
+
+func (d *DescendantQuery) Evaluate(t Iterator) interface{} {
+ d.Input.Evaluate(t)
+ d.iterator = nil
+ return d
+}
+
+func (d *DescendantQuery) Test(n xpath.NodeNavigator) bool {
+ return d.Predicate(n)
+}
+
+// FollowingQuery is an XPath following node query.(following::*|following-sibling::*)
+type FollowingQuery struct {
+ iterator func() xpath.NodeNavigator
+
+ Input Query
+ Sibling bool // The matching sibling node of current node.
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (f *FollowingQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if f.iterator == nil {
+ node := f.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ if f.Sibling {
+ f.iterator = func() xpath.NodeNavigator {
+ for {
+ if !node.MoveToNext() {
+ return nil
+ }
+ if f.Predicate(node) {
+ return node
+ }
+ }
+ }
+ } else {
+ var q Query // descendant query
+ f.iterator = func() xpath.NodeNavigator {
+ for {
+ if q == nil {
+ for !node.MoveToNext() {
+ if !node.MoveToParent() {
+ return nil
+ }
+ }
+ q = &DescendantQuery{
+ Self: true,
+ Input: &ContextQuery{},
+ Predicate: f.Predicate,
+ }
+ t.Current().MoveTo(node)
+ }
+ if node := q.Select(t); node != nil {
+ return node
+ }
+ q = nil
+ }
+ }
+ }
+ }
+
+ if node := f.iterator(); node != nil {
+ return node
+ }
+ f.iterator = nil
+ }
+}
+
+func (f *FollowingQuery) Evaluate(t Iterator) interface{} {
+ f.Input.Evaluate(t)
+ return f
+}
+
+func (f *FollowingQuery) Test(n xpath.NodeNavigator) bool {
+ return f.Predicate(n)
+}
+
+// PrecedingQuery is an XPath preceding node query.(preceding::*)
+type PrecedingQuery struct {
+ iterator func() xpath.NodeNavigator
+ Input Query
+ Sibling bool // The matching sibling node of current node.
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (p *PrecedingQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ if p.iterator == nil {
+ node := p.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ if p.Sibling {
+ p.iterator = func() xpath.NodeNavigator {
+ for {
+ for !node.MoveToPrevious() {
+ return nil
+ }
+ if p.Predicate(node) {
+ return node
+ }
+ }
+ }
+ } else {
+ var q Query
+ p.iterator = func() xpath.NodeNavigator {
+ for {
+ if q == nil {
+ for !node.MoveToPrevious() {
+ if !node.MoveToParent() {
+ return nil
+ }
+ }
+ q = &DescendantQuery{
+ Self: true,
+ Input: &ContextQuery{},
+ Predicate: p.Predicate,
+ }
+ t.Current().MoveTo(node)
+ }
+ if node := q.Select(t); node != nil {
+ return node
+ }
+ q = nil
+ }
+ }
+ }
+ }
+ if node := p.iterator(); node != nil {
+ return node
+ }
+ p.iterator = nil
+ }
+}
+
+func (p *PrecedingQuery) Evaluate(t Iterator) interface{} {
+ p.Input.Evaluate(t)
+ return p
+}
+
+func (p *PrecedingQuery) Test(n xpath.NodeNavigator) bool {
+ return p.Predicate(n)
+}
+
+// ParentQuery is an XPath parent node query.(parent::*)
+type ParentQuery struct {
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (p *ParentQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ node := p.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+ node = node.Copy()
+ if node.MoveToParent() && p.Predicate(node) {
+ return node
+ }
+ }
+}
+
+func (p *ParentQuery) Evaluate(t Iterator) interface{} {
+ p.Input.Evaluate(t)
+ return p
+}
+
+func (p *ParentQuery) Test(n xpath.NodeNavigator) bool {
+ return p.Predicate(n)
+}
+
+// SelfQuery is an Self node query.(self::*)
+type SelfQuery struct {
+ Input Query
+ Predicate func(xpath.NodeNavigator) bool
+}
+
+func (s *SelfQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ node := s.Input.Select(t)
+ if node == nil {
+ return nil
+ }
+
+ if s.Predicate(node) {
+ return node
+ }
+ }
+}
+
+func (s *SelfQuery) Evaluate(t Iterator) interface{} {
+ s.Input.Evaluate(t)
+ return s
+}
+
+func (s *SelfQuery) Test(n xpath.NodeNavigator) bool {
+ return s.Predicate(n)
+}
+
+// FilterQuery is an XPath query for predicate filter.
+type FilterQuery struct {
+ Input Query
+ Predicate Query
+}
+
+func (f *FilterQuery) do(t Iterator) bool {
+ val := reflect.ValueOf(f.Predicate.Evaluate(t))
+ switch val.Kind() {
+ case reflect.Bool:
+ return val.Bool()
+ case reflect.String:
+ return len(val.String()) > 0
+ case reflect.Float64:
+ pt := float64(getNodePosition(f.Input))
+ return int(val.Float()) == int(pt)
+ default:
+ if q, ok := f.Predicate.(Query); ok {
+ return q.Select(t) != nil
+ }
+ }
+ return false
+}
+
+func (f *FilterQuery) Select(t Iterator) xpath.NodeNavigator {
+ for {
+ node := f.Input.Select(t)
+ if node == nil {
+ return node
+ }
+ node = node.Copy()
+ //fmt.Println(node.LocalName())
+
+ t.Current().MoveTo(node)
+ if f.do(t) {
+ return node
+ }
+ }
+}
+
+func (f *FilterQuery) Evaluate(t Iterator) interface{} {
+ f.Input.Evaluate(t)
+ return f
+}
+
+// FunctionQuery is an XPath function that call a function to returns
+// value of current xpath.NodeNavigator node.
+type XPathFunction struct {
+ Input Query // Node Set
+ Func func(Query, Iterator) interface{} // The xpath function.
+}
+
+func (f *XPathFunction) Select(t Iterator) xpath.NodeNavigator {
+ return nil
+}
+
+// Evaluate call a specified function that will returns the
+// following value type: number,string,boolean.
+func (f *XPathFunction) Evaluate(t Iterator) interface{} {
+ return f.Func(f.Input, t)
+}
+
+// XPathConstant is an XPath constant operand.
+type XPathConstant struct {
+ Val interface{}
+}
+
+func (c *XPathConstant) Select(t Iterator) xpath.NodeNavigator {
+ return nil
+}
+
+func (c *XPathConstant) Evaluate(t Iterator) interface{} {
+ return c.Val
+}
+
+// LogicalExpr is an XPath logical expression.
+type LogicalExpr struct {
+ Left, Right Query
+
+ Do func(Iterator, interface{}, interface{}) interface{}
+}
+
+func (l *LogicalExpr) Select(t Iterator) xpath.NodeNavigator {
+ // When a XPath expr is logical expression.
+ node := t.Current().Copy()
+ val := l.Evaluate(t)
+ switch val.(type) {
+ case bool:
+ if val.(bool) == true {
+ return node
+ }
+ }
+ return nil
+}
+
+func (l *LogicalExpr) Evaluate(t Iterator) interface{} {
+ m := l.Left.Evaluate(t)
+ n := l.Right.Evaluate(t)
+ return l.Do(t, m, n)
+}
+
+// NumericExpr is an XPath numeric operator expression.
+type NumericExpr struct {
+ Left, Right Query
+
+ Do func(interface{}, interface{}) interface{}
+}
+
+func (n *NumericExpr) Select(t Iterator) xpath.NodeNavigator {
+ return nil
+}
+
+func (n *NumericExpr) Evaluate(t Iterator) interface{} {
+ m := n.Left.Evaluate(t)
+ k := n.Right.Evaluate(t)
+ return n.Do(m, k)
+}
+
+type BooleanExpr struct {
+ IsOr bool
+ Left, Right Query
+ iterator func() xpath.NodeNavigator
+}
+
+func (b *BooleanExpr) Select(t Iterator) xpath.NodeNavigator {
+ if b.iterator == nil {
+ var list []xpath.NodeNavigator
+ i := 0
+ root := t.Current().Copy()
+ if b.IsOr {
+ for {
+ node := b.Left.Select(t)
+ if node == nil {
+ break
+ }
+ node = node.Copy()
+ list = append(list, node)
+ }
+ t.Current().MoveTo(root)
+ for {
+ node := b.Right.Select(t)
+ if node == nil {
+ break
+ }
+ node = node.Copy()
+ list = append(list, node)
+ }
+ } else {
+ var m []xpath.NodeNavigator
+ var n []xpath.NodeNavigator
+ for {
+ node := b.Left.Select(t)
+ if node == nil {
+ break
+ }
+ node = node.Copy()
+ list = append(m, node)
+ }
+ t.Current().MoveTo(root)
+ for {
+ node := b.Right.Select(t)
+ if node == nil {
+ break
+ }
+ node = node.Copy()
+ list = append(n, node)
+ }
+ for _, k := range m {
+ for _, j := range n {
+ if k == j {
+ list = append(list, k)
+ }
+ }
+ }
+ }
+
+ b.iterator = func() xpath.NodeNavigator {
+ if i >= len(list) {
+ return nil
+ }
+ node := list[i]
+ i++
+ return node
+ }
+ }
+ return b.iterator()
+}
+
+func (b *BooleanExpr) Evaluate(t Iterator) interface{} {
+ m := b.Left.Evaluate(t)
+ if m.(bool) == b.IsOr {
+ return m
+ }
+ return b.Right.Evaluate(t)
+}
+
+func getNodePosition(q Query) int {
+ type Position interface {
+ position() int
+ }
+ if count, ok := q.(Position); ok {
+ return count.position()
+ }
+ return 1
+}
diff --git a/.svn/pristine/01/01fbd56a6bc1d05c1f484952a04efc5e992d3c89.svn-base b/.svn/pristine/01/01fbd56a6bc1d05c1f484952a04efc5e992d3c89.svn-base
new file mode 100644
index 0000000..aa66436
--- /dev/null
+++ b/.svn/pristine/01/01fbd56a6bc1d05c1f484952a04efc5e992d3c89.svn-base
@@ -0,0 +1,73 @@
+package fileUtil
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestTar(t *testing.T) {
+ path := GetCurrentPath()
+ fmt.Printf("CurrPath:%s\n", path)
+
+ fileName1 := fmt.Sprintf("%s/%s", path, "test1.txt")
+ fileName2 := fmt.Sprintf("%s/%s", path, "test2.txt")
+
+ if err := WriteFile(path, "test1.txt", true, "first line"); err != nil {
+ t.Errorf("there should be no error, but now it is:%s", err)
+ }
+ if err := WriteFile(path, "test2.txt", true, "first line"); err != nil {
+ t.Errorf("there should be no error, but now it is:%s", err)
+ }
+
+ sourceList := make([]string, 0, 2)
+ sourceList = append(sourceList, fileName1)
+ sourceList = append(sourceList, fileName2)
+ target := fmt.Sprintf("%s/%s", path, "test.tar")
+ if err := Tar(sourceList, target); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ }
+
+ if fileList, err := GetFileList(path); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ } else {
+ for _, item := range fileList {
+ fmt.Printf("item:%s\n", item)
+ }
+ }
+
+ DeleteFile(fileName1)
+ DeleteFile(fileName2)
+}
+
+func TestUntar(t *testing.T) {
+ path := GetCurrentPath()
+ fmt.Printf("CurrPath:%s\n", path)
+
+ source := fmt.Sprintf("%s/%s", path, "test.tar")
+ // target := path
+ target := ""
+ if err := Untar(source, target); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ }
+
+ if fileList, err := GetFileList(path); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ } else {
+ for _, item := range fileList {
+ fmt.Printf("item:%s\n", item)
+
+ if strings.HasSuffix(item, "txt") {
+ if content, err := ReadFileContent(item); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ } else {
+ fmt.Printf("content:%s\n", content)
+ }
+
+ DeleteFile(item)
+ }
+ }
+
+ DeleteFile(source)
+ }
+}
diff --git a/.svn/pristine/02/0299147d74eace2e9a84bcbe81bc0966d9a44600.svn-base b/.svn/pristine/02/0299147d74eace2e9a84bcbe81bc0966d9a44600.svn-base
new file mode 100644
index 0000000..5586a8f
--- /dev/null
+++ b/.svn/pristine/02/0299147d74eace2e9a84bcbe81bc0966d9a44600.svn-base
@@ -0,0 +1,35 @@
+package logUtilPlus
+
+import (
+ "testing"
+ "time"
+)
+
+func TestWrite(t *testing.T) {
+ Start("http://10.254.0.242:9200", "20008_gs_log", 20008)
+
+ InfoLog("日志测试")
+ WarnLog("日志测试")
+ DebugLog("日志测试")
+ ErrorLog("日志测试")
+ FatalLog("日志测试")
+
+ time.Sleep(1 * time.Second)
+ Stop()
+}
+
+func BenchmarkWrite(b *testing.B) {
+ Start("http://10.254.0.242:9200", "20008_gs_log", 20008)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ InfoLog("日志测试%d", i)
+ WarnLog("日志测试%d", i)
+ DebugLog("日志测试%d", i)
+ ErrorLog("日志测试%d", i)
+ FatalLog("日志测试%d", i)
+ }
+ b.StopTimer()
+
+ time.Sleep(1 * time.Second)
+ Stop()
+}
diff --git a/.svn/pristine/02/02bcd00feee3f43be99fed3c1fd0412e261ae3a5.svn-base b/.svn/pristine/02/02bcd00feee3f43be99fed3c1fd0412e261ae3a5.svn-base
new file mode 100644
index 0000000..ca200f1
--- /dev/null
+++ b/.svn/pristine/02/02bcd00feee3f43be99fed3c1fd0412e261ae3a5.svn-base
@@ -0,0 +1,88 @@
+package ini_config
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "testing"
+)
+
+func Test_File(t *testing.T) {
+ foder, _ := os.Getwd()
+ filePath := path.Join(foder, "ini.conf")
+
+ kvmap, err := ParseFile(filePath)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if len(kvmap) != 12 {
+ t.Error("读取的内容数量不正确")
+ return
+ }
+
+ if v, exists := kvmap["log.es.enable"]; exists == false || v != "false" {
+ t.Error("log.es.enable读取的值不正确")
+ }
+
+ if v, exists := kvmap["log.es.url"]; exists == false || v != "" {
+ t.Error("log.es.url读取的值不正确")
+ }
+}
+
+func Test_String(t *testing.T) {
+ k, v, err := Parse("log.es.enable")
+ if err == nil {
+ t.Error(fmt.Errorf("解析格式错误"))
+ return
+ }
+
+ k, v, err = Parse("log.es.enable=false #(false,默认值,关闭es日志记录,后续配置可不填写; true 打开日志记录)")
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if k != "log.es.enable" || v != "false" {
+ t.Error("解析的值不正确")
+ }
+
+ k, v, err = Parse("dbconnection=root:moqikaka3309!#@tcp(10.252.0.62:3309)/liangjian2_groupserver_auto_master?charset=utf8&parseTime=true&loc=Local&timeout=30s#数据库连接")
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if k != "dbconnection" || v != "root:moqikaka3309!#@tcp(10.252.0.62:3309)/liangjian2_groupserver_auto_master?charset=utf8&parseTime=true&loc=Local&timeout=30s" {
+ t.Error("解析的值不正确")
+ }
+
+}
+
+func Test_Content(t *testing.T) {
+ content := "#配置项说明\nlog.es.enable #(false,默认值,关闭es日志记录,后续配置可不填写; true 打开日志记录)\nlog.es.url= #(es服务地址)\nlog.es.indexName=1 #(es服务中Index名)\nlog.es.level=info #(debug|info|warn|error|fatal等级,等于或高于配置项则记录)\n\nlog.file.enable=false #(默认false)\nlog.file.path=log #(运行目录下log目录,默认logs)\nlog.file.pre=log #(文件名前缀,默认log)\nlog.file.enableHour=true #(文件以小时划分,格式:yyyyMMddHH,默认true,false 一天一个文件,格式:yyyyMMdd)\nlog.file.level=info\n\nlog.console.enable=false #(默认false)\nlog.console.level=info"
+ kvmap, err := ParseMultipleLines(content)
+ if err == nil {
+ t.Error(fmt.Errorf("配置格式不正确"))
+ return
+ }
+
+ content = "#配置项说明\nlog.es.enable=false #(false,默认值,关闭es日志记录,后续配置可不填写; true 打开日志记录)\nlog.es.url= #(es服务地址)\nlog.es.indexName=1 #(es服务中Index名)\nlog.es.level=info #(debug|info|warn|error|fatal等级,等于或高于配置项则记录)\n\nlog.file.enable=false #(默认false)\nlog.file.path=log #(运行目录下log目录,默认logs)\nlog.file.pre=log #(文件名前缀,默认log)\nlog.file.enableHour=true #(文件以小时划分,格式:yyyyMMddHH,默认true,false 一天一个文件,格式:yyyyMMdd)\nlog.file.level=info\n\nlog.console.enable=false #(默认false)\nlog.console.level=info"
+ kvmap, err = ParseMultipleLines(content)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if len(kvmap) != 11 {
+ t.Error("读取的内容数量不正确")
+ return
+ }
+
+ if v, exists := kvmap["log.es.enable"]; exists == false || v != "false" {
+ t.Error("log.es.enable读取的值不正确")
+ }
+
+ if v, exists := kvmap["log.es.url"]; exists == false || v != "" {
+ t.Error("log.es.url读取的值不正确")
+ }
+}
diff --git a/.svn/pristine/03/033f93a5ed351569e457445896fd1913ce46d45b.svn-base b/.svn/pristine/03/033f93a5ed351569e457445896fd1913ce46d45b.svn-base
new file mode 100644
index 0000000..3ec77dc
--- /dev/null
+++ b/.svn/pristine/03/033f93a5ed351569e457445896fd1913ce46d45b.svn-base
@@ -0,0 +1,98 @@
+package ipMgr
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestQuery(t *testing.T) {
+ IP_SERVICE_URL = "http://ipip.7qule.com/query"
+
+ appId := "unittest"
+ appId_wrong := "wrong"
+ appSecret := "c5746980-5d52-4ba9-834f-13d0066ad1d0"
+ appSecret_wrong := "wrong"
+ ip := "117.139.247.210"
+ ip_wrong := "wrong"
+ isDomestic := true
+ continent := ""
+ country := "中国"
+ region := "四川"
+ city := "成都"
+ timeout := 3
+
+ // Test with wrong AppId
+ ipInfoObj, err := Query(appId_wrong, appSecret, ip, isDomestic, timeout)
+ if err == nil {
+ t.Errorf("There should be an error, but now there is no error")
+ return
+ }
+
+ // Test with wrong AppSecret
+ ipInfoObj, err = Query(appId, appSecret_wrong, ip, isDomestic, timeout)
+ if err == nil {
+ t.Errorf("There should be an error, but now there is no error")
+ return
+ }
+
+ // Test with wrong IP
+ ipInfoObj, err = Query(appId, appSecret, ip_wrong, isDomestic, timeout)
+ if err == nil {
+ t.Errorf("There should be an error, but now there is no error")
+ return
+ }
+
+ // Test with correct information and domestic ip
+ ipInfoObj, err = Query(appId, appSecret, ip, isDomestic, timeout)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is one:%s", err)
+ return
+ }
+ fmt.Printf("ipInfoObj:%v\n", ipInfoObj)
+
+ if ipInfoObj.Continent != continent {
+ t.Errorf("Expected continent %s, but got %s", continent, ipInfoObj.Continent)
+ }
+
+ if ipInfoObj.Country != country {
+ t.Errorf("Expected country %s, but got %s", country, ipInfoObj.Country)
+ }
+
+ if ipInfoObj.Region != region {
+ t.Errorf("Expected region %s, but got %s", region, ipInfoObj.Region)
+ }
+
+ if ipInfoObj.City != city {
+ t.Errorf("Expected city %s, but got %s", city, ipInfoObj.City)
+ }
+
+ // Test with correct information and foreign ip
+ isDomestic = false
+ continent = "亚洲"
+ country = "中国"
+ region = "四川省"
+ city = "成都"
+
+ ipInfoObj, err = Query(appId, appSecret, ip, isDomestic, timeout)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is one:%s", err)
+ return
+ }
+ fmt.Printf("ipInfoObj:%v\n", ipInfoObj)
+
+ if ipInfoObj.Continent != continent {
+ t.Errorf("Expected continent %s, but got %s", continent, ipInfoObj.Continent)
+ }
+
+ if ipInfoObj.Country != country {
+ t.Errorf("Expected country %s, but got %s", country, ipInfoObj.Country)
+ }
+
+ if ipInfoObj.Region != region {
+ t.Errorf("Expected region %s, but got %s", region, ipInfoObj.Region)
+ }
+
+ if ipInfoObj.City != city {
+ t.Errorf("Expected city %s, but got %s", city, ipInfoObj.City)
+ }
+}
diff --git a/.svn/pristine/03/03df81ec69165cb7077f9e740559446368aca1f2.svn-base b/.svn/pristine/03/03df81ec69165cb7077f9e740559446368aca1f2.svn-base
new file mode 100644
index 0000000..3cb94b4
--- /dev/null
+++ b/.svn/pristine/03/03df81ec69165cb7077f9e740559446368aca1f2.svn-base
@@ -0,0 +1,78 @@
+package fileUtil
+
+import (
+ "compress/gzip"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+)
+
+// 对文件进行gzip压缩
+// source:源文件完整路径
+// target:目标文件文件夹(如果传空字符串,则为当前文件夹)
+// 返回值
+// 错误对象
+func Gzip(source, target string) error {
+ reader, err := os.Open(source)
+ if err != nil {
+ return err
+ }
+ defer reader.Close()
+
+ // 给目标文件夹赋值,如果传空,则默认为当前文件夹
+ if target == "" {
+ target = filepath.Dir(source)
+ }
+ fileName := filepath.Base(source)
+
+ targetFilePath := filepath.Join(target, fmt.Sprintf("%s.gz", fileName))
+ writer, err := os.Create(targetFilePath)
+ if err != nil {
+ return err
+ }
+ defer writer.Close()
+
+ archiver := gzip.NewWriter(writer)
+ archiver.Name = fileName
+ defer archiver.Close()
+
+ _, err = io.Copy(archiver, reader)
+
+ return err
+}
+
+// 对文件进行gzip解压缩
+// source:源文件完整路径
+// target:目标文件文件夹(解压缩文件的名字是内部自动赋值)
+// 返回值
+// 错误对象
+func UnGzip(source, target string) error {
+ reader, err := os.Open(source)
+ if err != nil {
+ return err
+ }
+ defer reader.Close()
+
+ archive, err := gzip.NewReader(reader)
+ if err != nil {
+ return err
+ }
+ defer archive.Close()
+
+ // 给目标文件夹赋值,如果传空,则默认为当前文件夹
+ if target == "" {
+ target = filepath.Dir(source)
+ }
+
+ targetFilePath := filepath.Join(target, archive.Name)
+ writer, err := os.Create(targetFilePath)
+ if err != nil {
+ return err
+ }
+ defer writer.Close()
+
+ _, err = io.Copy(writer, archive)
+
+ return err
+}
diff --git a/.svn/pristine/04/0418a758fbce45201919045075139dc8513be286.svn-base b/.svn/pristine/04/0418a758fbce45201919045075139dc8513be286.svn-base
new file mode 100644
index 0000000..c35cf5e
--- /dev/null
+++ b/.svn/pristine/04/0418a758fbce45201919045075139dc8513be286.svn-base
@@ -0,0 +1,67 @@
+package logUtil
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "testing"
+ "time"
+
+ impl_console "goutil/logUtil/impl-console"
+ impl_es "goutil/logUtil/impl-es"
+ impl_localfile "goutil/logUtil/impl-localfile"
+)
+
+func TestAllLog(t *testing.T) {
+ file, _ := exec.LookPath(os.Args[0])
+ path, _ := filepath.Abs(file)
+ logPath := filepath.Dir(path)
+
+ GetLocalFileLog().SetLogPath(logPath)
+
+ //添加控制台日志
+ consoleLog := impl_console.NewLogger()
+
+ //添加es日志
+ urls := []string{"http://10.1.0.71:9101/"}
+ eslog, err := impl_es.NewLogger(urls, "", "", "es_log_test", "les_log_test_innerid", nil)
+ if err != nil {
+ t.Error("esLog 创建失败")
+ }
+ SettingLogs([]ILog{consoleLog, eslog, impl_localfile.NewLogger()})
+
+ for i := 1; i < 10; i++ {
+ InfoLog("Info记录")
+ InfoLog("Info记录2:%v %v", i, time.Now())
+
+ DebugLog("Debug记录")
+ DebugLog("Debug记录2:%v %v", i, time.Now())
+
+ WarnLog("Warn记录")
+ WarnLog("Warn记录2:%v %v", i, time.Now())
+
+ ErrorLog("Error记录")
+ ErrorLog("ErrorLog记录2:%v %v", i, time.Now())
+
+ FatalLog("Fatal记录")
+ FatalLog("Fatal记录2:%v %v", i, time.Now())
+ }
+
+ time.Sleep(time.Second * 5)
+
+ Close(true)
+}
+
+func BenchmarkInfoLog(b *testing.B) {
+ file, _ := exec.LookPath(os.Args[0])
+ path, _ := filepath.Abs(file)
+ logPath := filepath.Dir(path)
+
+ GetLocalFileLog().SetLogPath(logPath)
+
+ for i := 0; i < b.N; i++ {
+ DebugLog("Debug 记录")
+ InfoLog("info记录 :%v", time.Now())
+ }
+ Close(true)
+}
diff --git a/.svn/pristine/04/044e3ac017ca5d27710d505ac314376753225cfc.svn-base b/.svn/pristine/04/044e3ac017ca5d27710d505ac314376753225cfc.svn-base
new file mode 100644
index 0000000..0e8bf38
--- /dev/null
+++ b/.svn/pristine/04/044e3ac017ca5d27710d505ac314376753225cfc.svn-base
@@ -0,0 +1,25 @@
+package managecenterMgr
+
+// ManageCenter数据获取开关(每一类数据一个开关)
+type ManageCenterDataSwitch struct {
+ // 获取所有数据开关(只要这个开关值为true,则不论各类数据的开关是否打开,都获取数据)
+ AllDataSwitch bool
+
+ // 获取合作商数据开关
+ PartnerDataSwitch bool
+
+ // 获取服务器数据开关
+ ServerDataSwitch bool
+
+ // 获取服务器组数开关
+ ServerGroupDataSwitch bool
+
+ // 获取资源包版本数据开关
+ ResourceVersionDataSwitch bool
+
+ // 获取白名单数据开关
+ WhiteListDataSwitch bool
+
+ // 获取大区数据开关
+ AreaDataSwitch bool
+}
diff --git a/.svn/pristine/04/04cc1937beadc6d8dace22ef80979ab50388eeea.svn-base b/.svn/pristine/04/04cc1937beadc6d8dace22ef80979ab50388eeea.svn-base
new file mode 100644
index 0000000..0cbb230
--- /dev/null
+++ b/.svn/pristine/04/04cc1937beadc6d8dace22ef80979ab50388eeea.svn-base
@@ -0,0 +1,38 @@
+module admincenter
+
+go 1.22.2
+
+replace (
+ common => ../common
+ framework => ../../framework
+ goutil => ../../goutil
+)
+
+require (
+ common v0.0.0-00010101000000-000000000000
+ goutil v0.0.0-20230425160006-b2d0b0a0b0b0
+)
+
+require (
+ filippo.io/edwards25519 v1.1.0 // indirect
+ framework v0.0.0-20230425160006-b2d0b0a0b0b0 // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+ github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4 // indirect
+ github.com/fatih/color v1.15.0 // indirect
+ github.com/go-redis/redis/v8 v8.11.5 // indirect
+ github.com/go-sql-driver/mysql v1.8.1 // indirect
+ github.com/gomodule/redigo v1.8.9 // indirect
+ github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/jinzhu/gorm v1.9.12 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.17 // indirect
+ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
+ golang.org/x/sys v0.6.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
+ gorm.io/driver/mysql v1.5.7 // indirect
+ gorm.io/gorm v1.25.12 // indirect
+)
diff --git a/.svn/pristine/04/04ff71b4d0991e86509f1059a6f59d487d6eadbf.svn-base b/.svn/pristine/04/04ff71b4d0991e86509f1059a6f59d487d6eadbf.svn-base
new file mode 100644
index 0000000..cb6a69c
--- /dev/null
+++ b/.svn/pristine/04/04ff71b4d0991e86509f1059a6f59d487d6eadbf.svn-base
@@ -0,0 +1,259 @@
+package timeUtil
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+
+ "goutil/stringUtil"
+)
+
+// format time like java, such as: yyyy-MM-dd HH:mm:ss
+// t:时间
+// format:格式化字符串
+// 返回值:
+// 格式化后的字符串
+func Format(t time.Time, format string) string {
+ //year
+ if strings.ContainsAny(format, "y") {
+ year := strconv.Itoa(t.Year())
+
+ if strings.Count(format, "yy") == 1 && strings.Count(format, "y") == 2 {
+ format = strings.Replace(format, "yy", year[2:], 1)
+ } else if strings.Count(format, "yyyy") == 1 && strings.Count(format, "y") == 4 {
+ format = strings.Replace(format, "yyyy", year, 1)
+ } else {
+ panic("format year error! please 'yyyy' or 'yy'")
+ }
+ }
+
+ //month
+ if strings.ContainsAny(format, "M") {
+ var month string
+
+ if int(t.Month()) < 10 {
+ month = "0" + strconv.Itoa(int(t.Month()))
+ } else {
+ month = strconv.Itoa(int(t.Month()))
+ }
+
+ if strings.Count(format, "MM") == 1 && strings.Count(format, "M") == 2 {
+ format = strings.Replace(format, "MM", month, 1)
+ } else {
+ panic("format month error! please 'MM'")
+ }
+ }
+
+ //day
+ if strings.ContainsAny(format, "d") {
+ var day string
+
+ if t.Day() < 10 {
+ day = "0" + strconv.Itoa(t.Day())
+ } else {
+ day = strconv.Itoa(t.Day())
+ }
+
+ if strings.Count(format, "dd") == 1 && strings.Count(format, "d") == 2 {
+ format = strings.Replace(format, "dd", day, 1)
+ } else {
+ panic("format day error! please 'dd'")
+ }
+ }
+
+ //hour
+ if strings.ContainsAny(format, "H") {
+ var hour string
+
+ if t.Hour() < 10 {
+ hour = "0" + strconv.Itoa(t.Hour())
+ } else {
+ hour = strconv.Itoa(t.Hour())
+ }
+
+ if strings.Count(format, "HH") == 1 && strings.Count(format, "H") == 2 {
+ format = strings.Replace(format, "HH", hour, 1)
+ } else {
+ panic("format hour error! please 'HH'")
+ }
+ }
+
+ //minute
+ if strings.ContainsAny(format, "m") {
+ var minute string
+
+ if t.Minute() < 10 {
+ minute = "0" + strconv.Itoa(t.Minute())
+ } else {
+ minute = strconv.Itoa(t.Minute())
+ }
+ if strings.Count(format, "mm") == 1 && strings.Count(format, "m") == 2 {
+ format = strings.Replace(format, "mm", minute, 1)
+ } else {
+ panic("format minute error! please 'mm'")
+ }
+ }
+
+ //second
+ if strings.ContainsAny(format, "s") {
+ var second string
+
+ if t.Second() < 10 {
+ second = "0" + strconv.Itoa(t.Second())
+ } else {
+ second = strconv.Itoa(t.Second())
+ }
+
+ if strings.Count(format, "ss") == 1 && strings.Count(format, "s") == 2 {
+ format = strings.Replace(format, "ss", second, 1)
+ } else {
+ panic("format second error! please 'ss'")
+ }
+ }
+
+ return format
+}
+
+// 转换成日期字符串
+// timeVal:待转换的时间
+// 返回值:
+// string:格式形如:2016-10-10
+/*
+前面是含义,后面是 go 的表示值,多种表示,逗号","分割
+月份 1,01,Jan,January
+日 2,02,_2
+时 3,03,15,PM,pm,AM,am
+分 4,04
+秒 5,05
+年 06,2006
+时区 -07,-0700,Z0700,Z07:00,-07:00,MST
+周几 Mon,Monday
+*/
+func ToDateString(timeVal time.Time) string {
+ return timeVal.Local().Format("2006-01-02")
+}
+
+// 忽略时区,转换成日期字符串
+// timeVal:待转换的时间
+// 返回值:
+// string:格式形如:2016-10-10
+/*
+前面是含义,后面是 go 的表示值,多种表示,逗号","分割
+月份 1,01,Jan,January
+日 2,02,_2
+时 3,03,15,PM,pm,AM,am
+分 4,04
+秒 5,05
+年 06,2006
+时区 -07,-0700,Z0700,Z07:00,-07:00,MST
+周几 Mon,Monday
+*/
+func ToDateString2(timeVal time.Time) string {
+ return timeVal.Format("2006-01-02")
+}
+
+// 以本地时区为准,转换成时间字符串
+// timeVal:待转换的时间
+// 返回值:
+// string:格式形如:2016-10-10 10:10:10
+/*
+前面是含义,后面是 go 的表示值,多种表示,逗号","分割
+月份 1,01,Jan,January
+日 2,02,_2
+时 3,03,15,PM,pm,AM,am
+分 4,04
+秒 5,05
+年 06,2006
+时区 -07,-0700,Z0700,Z07:00,-07:00,MST
+周几 Mon,Monday
+*/
+func ToDateTimeString(timeVal time.Time) string {
+ return ToDateTimeStringEx(timeVal, false)
+}
+
+func ToDateTimeStringEx(timeVal time.Time, flagT bool) string {
+ if flagT {
+ val := timeVal.Local().Format("2006-01-02 15:04:05")
+ return strings.Replace(val, " ", "T", -1)
+ }
+
+ return timeVal.Local().Format("2006-01-02 15:04:05")
+}
+
+// 忽略时区,转换成时间字符串
+// timeVal:待转换的时间
+// 返回值:
+// string:格式形如:2016-10-10 10:10:10
+/*
+前面是含义,后面是 go 的表示值,多种表示,逗号","分割
+月份 1,01,Jan,January
+日 2,02,_2
+时 3,03,15,PM,pm,AM,am
+分 4,04
+秒 5,05
+年 06,2006
+时区 -07,-0700,Z0700,Z07:00,-07:00,MST
+周几 Mon,Monday
+*/
+func ToDateTimeString2(timeVal time.Time) string {
+ return ToDateTimeStringEx2(timeVal, false)
+}
+
+// 日期和时间中间带T方式
+func ToDateTimeStringEx2(timeVal time.Time, flagT bool) string {
+ if flagT {
+ val := timeVal.Format("2006-01-02 15:04:05")
+ return strings.Replace(val, " ", "T", -1)
+ }
+
+ return timeVal.Format("2006-01-02 15:04:05")
+}
+
+// 转换成日期格式
+func ToDateTime(timeVal string) (time.Time, error) {
+ if stringUtil.IsEmpty(timeVal) {
+ return time.Time{}, fmt.Errorf("timeval is empty")
+ }
+
+ return time.ParseInLocation("2006-01-02 15:04:05", timeVal, time.Local)
+}
+
+// 以指定时区,转换成日期格式
+func ToDateTime2(timeVal string, location *time.Location) (time.Time, error) {
+ if stringUtil.IsEmpty(timeVal) {
+ return time.Time{}, fmt.Errorf("timeval is empty")
+ }
+
+ return time.ParseInLocation("2006-01-02 15:04:05", timeVal, location)
+}
+
+// 转换成时间格式
+func ToDate(timeVal string) (time.Time, error) {
+ if stringUtil.IsEmpty(timeVal) {
+ return time.Time{}, fmt.Errorf("timeval is empty")
+ }
+
+ return time.ParseInLocation("2006-01-02", timeVal, time.Local)
+}
+
+// 转换成时间格式
+func ToDate2(timeVal string, location *time.Location) (time.Time, error) {
+ if stringUtil.IsEmpty(timeVal) {
+ return time.Time{}, fmt.Errorf("timeval is empty")
+ }
+
+ return time.ParseInLocation("2006-01-02", timeVal, location)
+}
+
+// 转换成yyyyMMddHHmmssms的格式
+func ToInt64(timeVal time.Time) int64 {
+ year := timeVal.Year()
+ month := int(timeVal.Month())
+ day := timeVal.Day()
+ hour := timeVal.Hour()
+ minute := timeVal.Minute()
+ second := timeVal.Second()
+
+ return int64(int64(year)*1e10) + int64(month*1e8) + int64(day*1e6) + int64(hour*1e4) + int64(minute*1e2) + int64(second)
+}
diff --git a/.svn/pristine/05/051936fe62906601a10b242b5729b54e02e6890c.svn-base b/.svn/pristine/05/051936fe62906601a10b242b5729b54e02e6890c.svn-base
new file mode 100644
index 0000000..541a306
--- /dev/null
+++ b/.svn/pristine/05/051936fe62906601a10b242b5729b54e02e6890c.svn-base
@@ -0,0 +1,19 @@
+package game
+
+import "common/connection"
+
+func init() {
+ //注册数据库
+ connection.RegisterDBModel(&Game{})
+}
+
+type Game struct {
+ GameID int64 `gorm:"column:game_id;primary_key;comment:用户id;autoIncrementIncrement" json:"gameid"`
+
+ //账号
+ Account string `gorm:"column:account;comment:账号" json:"account"`
+}
+
+func (Game) TableName() string {
+ return "user"
+}
diff --git a/.svn/pristine/06/067c32d6d970c791745423200210d5c8eced9132.svn-base b/.svn/pristine/06/067c32d6d970c791745423200210d5c8eced9132.svn-base
new file mode 100644
index 0000000..1c8739a
--- /dev/null
+++ b/.svn/pristine/06/067c32d6d970c791745423200210d5c8eced9132.svn-base
@@ -0,0 +1,80 @@
+package gameLogMgr
+
+import (
+ "fmt"
+
+ "github.com/Shopify/sarama"
+ "goutil/debugUtil"
+ "goutil/logUtilPlus"
+)
+
+var (
+ producer sarama.AsyncProducer
+)
+
+// 启动生产者
+// 参数:
+// brokerList:Broker地址
+// userId:用户名(可默认为空字符串)
+// passWard:密码(可默认为空字符串)
+// 返回值:
+// 无
+func Start(brokerList []string, userId string, passWard string) {
+ /*
+ 设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”消息的定义。如果设置成 all,则表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。
+ 对于游戏日志,设置为WaitForLocal即可;如果是游戏数据,则应设置为WaitForAll
+ 设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
+ */
+ var err error
+ config := sarama.NewConfig()
+
+ config.Net.SASL.User = userId
+ config.Net.SASL.Password = passWard
+ config.Producer.Return.Successes = false
+ config.Producer.Return.Errors = true
+ config.Producer.Retry.Max = 10
+ config.Producer.RequiredAcks = sarama.WaitForLocal
+ producer, err = sarama.NewAsyncProducer(brokerList, config)
+ if err != nil {
+ panic(fmt.Errorf("Kafka Start failed. Error: %v\n", err))
+ }
+
+ go func() {
+ for err := range producer.Errors() {
+ debugUtil.Printf("Send message to kafka failed. Error: %v\n", err.Err)
+ logUtilPlus.ErrorLog("Send message to kafka failed. Error: %v\n", err.Err)
+ }
+ }()
+}
+
+func Stop() {
+ if producer != nil {
+ err := producer.Close()
+ if err != nil {
+ debugUtil.Printf("Stop kafka failed. Error: %v\n", err)
+ logUtilPlus.ErrorLog("Stop kafka failed. Error: %v\n", err)
+ }
+ }
+}
+
+// 写入游戏日志
+// 参数:
+// serverGroupId: 游戏服务器组Id
+// key: 标识
+// message: 日志
+// 返回值: 无
+func Write(topic string, serverGroupId int32, message string) {
+ if producer == nil {
+ debugUtil.Printf("Send message to kafka failed. producer is nil")
+ logUtilPlus.ErrorLog("Send message to kafka failed. producer is nil")
+ return
+ }
+
+ msg := &sarama.ProducerMessage{}
+ msg.Topic = topic
+ msg.Key = sarama.StringEncoder(fmt.Sprintf("%d", serverGroupId))
+ msg.Value = sarama.ByteEncoder(message)
+
+ // Send to kafka
+ producer.Input() <- msg
+}
diff --git a/.svn/pristine/07/0782015460cfe541898e77c9fb5904023dcd9457.svn-base b/.svn/pristine/07/0782015460cfe541898e77c9fb5904023dcd9457.svn-base
new file mode 100644
index 0000000..cbbbf18
--- /dev/null
+++ b/.svn/pristine/07/0782015460cfe541898e77c9fb5904023dcd9457.svn-base
@@ -0,0 +1,14 @@
+package gameLogMgr
+
+// 游戏日志对象
+type GameLog struct {
+ ServerGroupId int32 // 服务器组Id
+ LogSql string // 日志Sql
+}
+
+func newGameLog(serverGroupId int32, logSql string) *GameLog {
+ return &GameLog{
+ ServerGroupId: serverGroupId,
+ LogSql: logSql,
+ }
+}
diff --git a/.svn/pristine/07/07ce17462368c2b1dc512b9b3abd7951d62168e5.svn-base b/.svn/pristine/07/07ce17462368c2b1dc512b9b3abd7951d62168e5.svn-base
new file mode 100644
index 0000000..af97244
--- /dev/null
+++ b/.svn/pristine/07/07ce17462368c2b1dc512b9b3abd7951d62168e5.svn-base
@@ -0,0 +1,13 @@
+package mysqlSync
+
+/*
+提供数据同步到mysql的方法。基本逻辑如下:
+1、对外接收数据,以追加的方式保存到大文件中。数据的格式为:header(4bytes)+content。
+2、启动独立的goroutine来从大文件中读取数据,并保存到数据库中。
+3、使用syncInfo.txt文件保存当前已经处理的文件的路径,以及下一次将要读取的文件的Offset。为了降低向syncInfo.txt文件中写入失败,
+导致需要从头开始同步数据,所以采用了在指定数目的范围内以追加形式来写入数据的方式;只有达到了指定数量才会将整个文件清空。
+
+对于错误的处理方式,分为以下两种:
+1、文件错误:由于文件系统是本系统的核心,所以如果出现文件的读写出错,则需要终止整个进程,所以需要抛出panic。
+2、数据库错误:当数据库不可访问时,为了不影响整个外部进程的运行,故而不抛出panic,而只是通过monitorNewMgr.Report的方式来报告故障。
+*/
diff --git a/.svn/pristine/08/08ab382d97d7dc9708f61a91bdf317d06b7b7d83.svn-base b/.svn/pristine/08/08ab382d97d7dc9708f61a91bdf317d06b7b7d83.svn-base
new file mode 100644
index 0000000..a634f51
--- /dev/null
+++ b/.svn/pristine/08/08ab382d97d7dc9708f61a91bdf317d06b7b7d83.svn-base
@@ -0,0 +1,18 @@
+package mqMgr
+
+// 地域
+const (
+ MQ_REGION_GUANGZHOU = "gz"
+ MQ_REGION_SAHNGHAI = "sh"
+ MQ_REGION_BEIJING = "bj"
+ MQ_REGION_SHANGHAIJINRONG = "shjr"
+ MQ_REGION_SHENZHENJINRONG = "szjr"
+ MQ_REGION_HONGKONG = "hk"
+ MQ_REGION_CHENGDU = "cd"
+ MQ_REGION_CANADA = "ca"
+ MQ_REGION_UNITED_STATES_EAST = "use"
+ MQ_REGION_UNITED_STATES_WEST = "usw"
+ MQ_REGION_INDIA = "in"
+ MQ_REGION_THILAND = "th"
+ MQ_REGION_SINGAPORE = "sg"
+)
diff --git a/.svn/pristine/09/0973b54e789e52c6207035406c7a797712e93165.svn-base b/.svn/pristine/09/0973b54e789e52c6207035406c7a797712e93165.svn-base
new file mode 100644
index 0000000..c56ec77
--- /dev/null
+++ b/.svn/pristine/09/0973b54e789e52c6207035406c7a797712e93165.svn-base
@@ -0,0 +1,265 @@
+package typeUtil
+
+import (
+ "fmt"
+ "time"
+)
+
+// KeyValue数据集合
+type MapData map[string]interface{}
+
+// 创建新的MapData
+// mapData:原有的map数据
+// 返回
+// 新的Map对象
+func NewMapData(mapData map[string]interface{}) MapData {
+ return MapData(mapData)
+}
+
+// 类型转换为byte
+// 返回值:
+// byte:结果
+// error:错误数据
+func (this MapData) Byte(key string) (value byte, err error) {
+ return this.Uint8(key)
+}
+
+// 类型转换为int
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Int(key string) (value int, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Int(val)
+ return
+}
+
+// 类型转换为int8
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Int8(key string) (value int8, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Int8(val)
+ return
+}
+
+// 类型转换为int16
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Int16(key string) (value int16, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Int16(val)
+ return
+}
+
+// 类型转换为int32
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Int32(key string) (value int32, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Int32(val)
+ return
+}
+
+// 类型转换为int64
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Int64(key string) (value int64, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Int64(val)
+ return
+}
+
+// 类型转换为uint
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Uint(key string) (value uint, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Uint(val)
+ return
+}
+
+// 类型转换为uint8
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Uint8(key string) (value uint8, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Uint8(val)
+ return
+}
+
+// 类型转换为uint16
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Uint16(key string) (value uint16, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Uint16(val)
+ return
+}
+
+// 类型转换为uint32
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Uint32(key string) (value uint32, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Uint32(val)
+ return
+}
+
+// 类型转换为uint64
+// 返回值:
+// int:结果
+// error:错误数据
+func (this MapData) Uint64(key string) (value uint64, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Uint64(val)
+ return
+}
+
+// 类型转换为float32
+// 返回值:
+// float64:结果
+// error:错误数据
+func (this MapData) Float32(key string) (value float32, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Float32(val)
+ return
+}
+
+// 类型转换为float64
+// 返回值:
+// float64:结果
+// error:错误数据
+func (this MapData) Float64(key string) (value float64, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Float64(val)
+ return
+}
+
+// 类型转换为bool
+// 返回值:
+// bool:结果
+// error:错误信息
+func (this MapData) Bool(key string) (value bool, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = Bool(val)
+ return
+}
+
+// 类型转换为字符串
+// 返回值:
+// string:结果
+// error:错误信息
+func (this MapData) String(key string) (value string, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = String(val)
+ return
+}
+
+// 转换为时间格式,如果是字符串,则要求内容格式形如:2017-02-14 05:20:00
+// 返回值:
+// bool:结果
+// error:错误信息
+func (this MapData) DateTime(key string) (value time.Time, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value, err = DateTime(val)
+ return
+}
+
+// 获取指定的值
+// 返回值:
+// interface{}:结果
+// error:错误信息
+func (this MapData) Interface(key string) (value interface{}, err error) {
+ val, exist := this[key]
+ if exist == false || val == nil {
+ err = fmt.Errorf("Target key: [%s] doesn't exist", key)
+ return
+ }
+
+ value = val
+ return
+}
diff --git a/.svn/pristine/09/09b7f50515939483a29f46f368d7bd7db0165b49.svn-base b/.svn/pristine/09/09b7f50515939483a29f46f368d7bd7db0165b49.svn-base
new file mode 100644
index 0000000..a6b18ae
--- /dev/null
+++ b/.svn/pristine/09/09b7f50515939483a29f46f368d7bd7db0165b49.svn-base
@@ -0,0 +1,73 @@
+package shortUrlMgr
+
+import (
+ "encoding/json"
+ "fmt"
+ "time"
+
+ "goutil/securityUtil"
+ "goutil/stringUtil"
+ "goutil/webUtil"
+)
+
+var (
+ ShortUrl_SERVICE_URL = "http://a.app366.com/get"
+)
+
+// 服务器的响应对象
+type QueryResponse struct {
+ // 响应结果的状态值
+ ResultStatus string
+
+ // 响应结果的数据
+ Data string
+}
+
+// 获取短链
+// appId: 为应用分配的唯一标识
+// appSecret: 为应用分配的密钥
+// fullUrl: 完整的Url
+// timeout:超时时间(单位:秒)
+// 返回值:
+// ipInfoObj: IP地址信息对象
+// err: 错误对象
+func GetShortUrl(appId, appSecret, fullUrl string, timeout int) (shortUrl string, err error) {
+ timeStamp := fmt.Sprintf("%d", time.Now().Unix())
+ fullUrl = stringUtil.Base64Encode(fullUrl)
+ rawString := fmt.Sprintf("AppId=%s&FullUrl=%s&Timestamp=%s&AppSecret=%s", appId, fullUrl, timeStamp, appSecret)
+ sign := securityUtil.Md5String(rawString, true)
+
+ postData := make(map[string]string, 5)
+ postData["AppId"] = appId
+ postData["FullUrl"] = fullUrl
+ postData["Timestamp"] = timeStamp
+ postData["Sign"] = sign
+
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, timeout)
+ statusCode, result, err := webUtil.PostMapData(ShortUrl_SERVICE_URL, postData, header, transport)
+ if err != nil {
+ return
+ }
+ if statusCode != 200 {
+ err = fmt.Errorf("StatusCode:%d is wrong.", statusCode)
+ return
+ }
+
+ var queryResponseObj *QueryResponse
+ err = json.Unmarshal(result, &queryResponseObj)
+ if err != nil {
+ return
+ }
+
+ if queryResponseObj.ResultStatus != "" {
+ err = fmt.Errorf("Query result:%s", queryResponseObj.ResultStatus)
+ return
+ }
+
+ shortUrl = queryResponseObj.Data
+
+ return
+}
diff --git a/.svn/pristine/0a/0a32a7aadf4e5244aa44094b27c6e4e39d8a1f2d.svn-base b/.svn/pristine/0a/0a32a7aadf4e5244aa44094b27c6e4e39d8a1f2d.svn-base
new file mode 100644
index 0000000..0c2a186
--- /dev/null
+++ b/.svn/pristine/0a/0a32a7aadf4e5244aa44094b27c6e4e39d8a1f2d.svn-base
@@ -0,0 +1,39 @@
+package reloadMgr
+
+import (
+ "fmt"
+
+ "goutil/logUtil"
+)
+
+var (
+ reloadFuncMap = make(map[string]func() error)
+)
+
+// RegisterReloadFunc ...注册Reload方法
+// funcName:方法名称
+// reloadFunc:reload方法
+func RegisterReloadFunc(funcName string, reloadFunc func() error) {
+ if _, exists := reloadFuncMap[funcName]; exists {
+ panic(fmt.Sprintf("%s已经存在,请重新取名", funcName))
+ }
+
+ reloadFuncMap[funcName] = reloadFunc
+ logUtil.InfoLog(fmt.Sprintf("RegisterReloadFunc funcName:%s,当前共有%d个注册", funcName, len(reloadFuncMap)))
+}
+
+// Reload ...重新加载
+// 返回值:
+// 错误列表
+func Reload() (errList []error) {
+ for funcName, reloadFunc := range reloadFuncMap {
+ if err := reloadFunc(); err == nil {
+ logUtil.InfoLog(fmt.Sprintf("Call ReloadFunc:%s Success.", funcName))
+ } else {
+ logUtil.ErrorLog(fmt.Sprintf("Call ReloadFunc:%s Fail, Error:%s", funcName, err))
+ errList = append(errList, err)
+ }
+ }
+
+ return
+}
diff --git a/.svn/pristine/0a/0a359deb9b9471a4ea96b66c1cc364911ab54b99.svn-base b/.svn/pristine/0a/0a359deb9b9471a4ea96b66c1cc364911ab54b99.svn-base
new file mode 100644
index 0000000..08b6989
--- /dev/null
+++ b/.svn/pristine/0a/0a359deb9b9471a4ea96b66c1cc364911ab54b99.svn-base
@@ -0,0 +1,55 @@
+package stringUtil
+
+import (
+ "encoding/base64"
+)
+
+const (
+ base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+
+// const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+// const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
+)
+
+var coder = base64.NewEncoding(base64Table)
+
+// 对字符串进行Base64编码
+func Base64Encode(src string) string {
+ if src == "" {
+ return src
+ }
+
+ return base64.StdEncoding.EncodeToString([]byte(src))
+}
+
+// 对字符串进行Base64解码
+func Base64Encode2(src []byte) []byte {
+ if len(src) == 0 {
+ return src
+ }
+
+ return []byte(base64.StdEncoding.EncodeToString(src))
+}
+
+// 对字符数组进行Base64编码
+func Base64Decode(src string) (string, error) {
+ if src == "" {
+ return src, nil
+ }
+
+ bytes, err := coder.DecodeString(src)
+ if err != nil {
+ return "", err
+ }
+
+ return string(bytes), nil
+}
+
+// 对字符数组进行Base64解码
+func Base64Decode2(src []byte) ([]byte, error) {
+ if len(src) == 0 {
+ return src, nil
+ }
+
+ return coder.DecodeString(string(src))
+}
diff --git a/.svn/pristine/0a/0a5860746a4b445d18be34fff4f29b1e4b180b35.svn-base b/.svn/pristine/0a/0a5860746a4b445d18be34fff4f29b1e4b180b35.svn-base
new file mode 100644
index 0000000..1644bfe
--- /dev/null
+++ b/.svn/pristine/0a/0a5860746a4b445d18be34fff4f29b1e4b180b35.svn-base
@@ -0,0 +1,41 @@
+// ************************************
+// @package: handleMgr
+// @description: 反射类-反射的方法和输入、输出参数类型组合类型
+// @author:
+// @revision history:
+// @create date: 2022-02-23 16:33:43
+// ************************************
+
+package handleMgr
+
+import (
+ "reflect"
+)
+
+// ReflectMethod 反射的方法和输入、输出参数类型组合类型
+type ReflectMethod struct {
+ // 反射出来的对应方法对象
+ Method reflect.Value
+
+ // 反射出来的方法的输入参数的类型集合
+ InTypes []reflect.Type
+
+ // 反射出来的方法的输出参数的类型集合
+ OutTypes []reflect.Type
+}
+
+// NewReflectMethod
+// @description:创建反射的方法和输入、输出参数类型组合类型
+// parameter:
+// @_method:反射出来的对应方法对象
+// @_inTypes:反射出来的方法的输入参数的类型集合
+// @_outTypes:反射出来的方法的输出参数的类型集合
+// return:
+// @*ReflectMethod:
+func NewReflectMethod(_method reflect.Value, _inTypes []reflect.Type, _outTypes []reflect.Type) *ReflectMethod {
+ return &ReflectMethod{
+ Method: _method,
+ InTypes: _inTypes,
+ OutTypes: _outTypes,
+ }
+}
diff --git a/.svn/pristine/0a/0aad8def9322e065863083d01d249ef44cf69dc5.svn-base b/.svn/pristine/0a/0aad8def9322e065863083d01d249ef44cf69dc5.svn-base
new file mode 100644
index 0000000..5a3794f
--- /dev/null
+++ b/.svn/pristine/0a/0aad8def9322e065863083d01d249ef44cf69dc5.svn-base
@@ -0,0 +1,4 @@
+/*
+提供时间相关的一些助手方法
+*/
+package timeUtil
diff --git a/.svn/pristine/0b/0b64d992d48171632e253b32b808a1222c5e7681.svn-base b/.svn/pristine/0b/0b64d992d48171632e253b32b808a1222c5e7681.svn-base
new file mode 100644
index 0000000..f5bcaeb
--- /dev/null
+++ b/.svn/pristine/0b/0b64d992d48171632e253b32b808a1222c5e7681.svn-base
@@ -0,0 +1,33 @@
+package exitMgr
+
+import (
+ "fmt"
+
+ "goutil/logUtil"
+)
+
+var (
+ exitFuncMap = make(map[string]func())
+)
+
+// RegisterExitFunc ...注册Exit方法
+// funcName:方法名称
+// exitFunc:exit方法
+func RegisterExitFunc(funcName string, exitFunc func()) {
+ if _, exists := exitFuncMap[funcName]; exists {
+ panic(fmt.Sprintf("%s已经存在,请重新取名", funcName))
+ }
+
+ exitFuncMap[funcName] = exitFunc
+ logUtil.InfoLog("RegisterExitFunc funcName:%s,当前共有%d个注册", funcName, len(exitFuncMap))
+}
+
+// Exit ...退出程序
+// 返回值:
+// 无
+func Exit() {
+ for funcName, exitFunc := range exitFuncMap {
+ exitFunc()
+ logUtil.InfoLog("Call ExitFunc:%s Finish.", funcName)
+ }
+}
diff --git a/.svn/pristine/0b/0b6d198d02242d905fb9068a5756c87c3a5aa2fe.svn-base b/.svn/pristine/0b/0b6d198d02242d905fb9068a5756c87c3a5aa2fe.svn-base
new file mode 100644
index 0000000..7c518a7
--- /dev/null
+++ b/.svn/pristine/0b/0b6d198d02242d905fb9068a5756c87c3a5aa2fe.svn-base
@@ -0,0 +1,7 @@
+package mqMgr
+
+// 消息队列类型:消息队列、消息主题
+const (
+ MQ_TYPE_QUEUE = "queue"
+ MQ_TYPE_TOPIC = "topic"
+)
diff --git a/.svn/pristine/0c/0c649c8389b0629d492c0cc4dab91d9b280686d2.svn-base b/.svn/pristine/0c/0c649c8389b0629d492c0cc4dab91d9b280686d2.svn-base
new file mode 100644
index 0000000..f505d70
--- /dev/null
+++ b/.svn/pristine/0c/0c649c8389b0629d492c0cc4dab91d9b280686d2.svn-base
@@ -0,0 +1,44 @@
+package intUtil
+
+import (
+ "fmt"
+ "math/rand"
+ "time"
+)
+
+// ShuffleIntDigits 打乱整数的各个数字位置并返回新的整数
+func ShuffleIntDigits(num int64) (int64, error) {
+ if num < 0 {
+ return 0, fmt.Errorf("number must be non-negative")
+ }
+
+ var digits []int64
+ for num > 0 {
+ digits = append(digits, num%10)
+ num /= 10
+ }
+
+ // 如果原始数字是0,直接返回
+ if len(digits) == 0 {
+ return 0, nil
+ }
+
+ // 反转切片以保持原来的数字顺序
+ for i, j := 0, len(digits)-1; i < j; i, j = i+1, j-1 {
+ digits[i], digits[j] = digits[j], digits[i]
+ }
+
+ // 打乱数字切片
+ rand.Seed(time.Now().UnixNano())
+ rand.Shuffle(len(digits), func(i, j int) {
+ digits[i], digits[j] = digits[j], digits[i]
+ })
+
+ // 重新组合为新的整数
+ result := int64(0)
+ for _, digit := range digits {
+ result = result*10 + digit
+ }
+
+ return result, nil
+}
diff --git a/.svn/pristine/0c/0cc6a8594a211ca755865be522ee4fc139d7b3f1.svn-base b/.svn/pristine/0c/0cc6a8594a211ca755865be522ee4fc139d7b3f1.svn-base
new file mode 100644
index 0000000..ca819e2
--- /dev/null
+++ b/.svn/pristine/0c/0cc6a8594a211ca755865be522ee4fc139d7b3f1.svn-base
@@ -0,0 +1,19 @@
+package qcloud
+
+// 发送模板短信字段
+type tmplSmsField struct {
+ // 签名 (前缀)
+ Sign string `json:"sign,omitempty"`
+ // 模板id
+ Tpl_id int `json:"tpl_id,omitempty"`
+ // 模板参数
+ Params []string `json:"params,omitempty"`
+}
+
+func newTmplSmsField(sign string, id int, params []string) *tmplSmsField {
+ return &tmplSmsField{
+ Sign: sign,
+ Tpl_id: id,
+ Params: params,
+ }
+}
diff --git a/.svn/pristine/0c/0ce1ecad1add98c087081650bab4b1dc4ba8424b.svn-base b/.svn/pristine/0c/0ce1ecad1add98c087081650bab4b1dc4ba8424b.svn-base
new file mode 100644
index 0000000..7df1797
--- /dev/null
+++ b/.svn/pristine/0c/0ce1ecad1add98c087081650bab4b1dc4ba8424b.svn-base
@@ -0,0 +1,41 @@
+package monitorNewMgr
+
+// 监控信息传输对象
+type MonitorModel struct {
+ //状态码 0 是心跳,非零为错误信息
+ Code int `json:"Code"`
+
+ //组Id
+ GroupId string `json:"GroupId"`
+
+ //组密钥
+ ProjectId string `json:"ProjectId"`
+
+ //项目Id
+ ServerIp string `json:"ServerIp"`
+
+ // 监控使用的服务器IP
+ ServerName string `json:"ServerName"`
+
+ // 监控使用的服务器名称
+ Content string `json:"Content"`
+
+ // 消息产生时的时间戳
+ Timestamp int64 `json:"Timestamp"`
+
+ // 签名
+ Sign string `json:"Sign"`
+}
+
+func newMonitorModel(code int, groupId, projectId, serverIp, serverName, content string, timestamp int64, sign string) *MonitorModel {
+ return &MonitorModel{
+ Code: code,
+ GroupId: groupId,
+ ProjectId: projectId,
+ ServerIp: serverIp,
+ ServerName: serverName,
+ Content: content,
+ Timestamp: timestamp,
+ Sign: sign,
+ }
+}
diff --git a/.svn/pristine/0c/0cf6873b2c63205e8f54bb6bb60b43880f54c4a8.svn-base b/.svn/pristine/0c/0cf6873b2c63205e8f54bb6bb60b43880f54c4a8.svn-base
new file mode 100644
index 0000000..be896d2
--- /dev/null
+++ b/.svn/pristine/0c/0cf6873b2c63205e8f54bb6bb60b43880f54c4a8.svn-base
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "common/connection"
+ "sync"
+
+ _ "common/resultStatus"
+ "common/webServer"
+ _ "logincenter/internal/user"
+)
+
+var (
+ wg sync.WaitGroup
+)
+
+func init() {
+ // 设置WaitGroup需要等待的数量,只要有一个服务器出现错误都停止服务器
+ wg.Add(1)
+}
+
+func main() {
+
+ //加载配置
+ loadConfig()
+
+ // 启动webserver
+ go webServer.Start(&wg)
+
+ // 阻塞等待,以免main线程退出
+ wg.Wait()
+}
+
+// loadConfig 用于加载配置信息。
+// 该函数会读取配置文件或环境变量中的设置,并根据这些设置初始化程序所需的配置。
+// 目前函数的实现为空,需要根据实际的配置加载逻辑进行填充。
+func loadConfig() {
+
+ //设置数据类型
+ connection.SetModelDB(connection.GetUserDB())
+
+ //构建数据库
+ connection.BuildDB()
+}
diff --git a/.svn/pristine/0d/0d81a7654b3ab7b1fa88a882ac9120820be781d1.svn-base b/.svn/pristine/0d/0d81a7654b3ab7b1fa88a882ac9120820be781d1.svn-base
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.svn/pristine/0d/0d81a7654b3ab7b1fa88a882ac9120820be781d1.svn-base
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.svn/pristine/0d/0de3f1598f1552816faf3d86834fb1b66bf8bf50.svn-base b/.svn/pristine/0d/0de3f1598f1552816faf3d86834fb1b66bf8bf50.svn-base
new file mode 100644
index 0000000..3796ce7
--- /dev/null
+++ b/.svn/pristine/0d/0de3f1598f1552816faf3d86834fb1b66bf8bf50.svn-base
@@ -0,0 +1,155 @@
+package gameServerMgr
+
+import (
+ "crypto/tls"
+ "encoding/json"
+ "fmt"
+ "strconv"
+
+ . "Framework/managecenterModel"
+ "goutil/webUtil"
+ "goutil/zlibUtil"
+)
+
+// 区服激活地址后缀
+const ActivateServer_URL_SUFFIX string = "/API/ServerActivate.ashx"
+
+var (
+ mManageCenterServerAPIUrl string
+ mIsInit bool = true
+)
+
+// 解析从ManagecenterServer中获取的服务器相关数据
+func ParseInfoFromManageCenterServer(serverGroupId int32, data string) {
+ var deserializedData map[string]interface{}
+ err := json.Unmarshal([]byte(data), &deserializedData)
+ if err != nil {
+ return
+ }
+
+ //解析服务器组
+ var serverGroup *ServerGroup
+ err = json.Unmarshal([]byte(deserializedData["ServerGroupInfo"].(string)), &serverGroup)
+ if err != nil {
+ return
+ }
+
+ //解析合作商
+ var partnerList []*Partner
+ err = json.Unmarshal([]byte(deserializedData["PartnerList"].(string)), &partnerList)
+ if err != nil {
+ return
+ }
+
+ //解析服务器列表
+ var serverList []*Server
+ err = json.Unmarshal([]byte(deserializedData["ServerList"].(string)), &serverList)
+ if err != nil {
+ return
+ }
+
+ //解析资源包
+ var resourceList []*ResourceVersion
+ err = json.Unmarshal([]byte(deserializedData["ResourceVersionList"].(string)), &resourceList)
+ if err != nil {
+ return
+ }
+
+ //解析大区
+ var areaList []*Area
+ err = json.Unmarshal([]byte(deserializedData["AreaList"].(string)), &areaList)
+ if err != nil {
+ return
+ }
+
+ //判断是否需要更新数据(如果ServerGroupId不匹配,则不解析数据)
+ if serverGroupId != serverGroup.Id {
+ return
+ }
+
+ //缓存服务器组
+ ParseServerGroupInfo(serverGroup)
+
+ //缓存合作商
+ ParsePartnerInfo(partnerList)
+
+ //缓存合作商对应的充值配置
+ ParseChargeConfigInfo(partnerList)
+
+ //缓存服务器
+ ParseServerInfo(serverList)
+
+ //缓存资源包
+ ParseResourceVersionInfo(resourceList)
+
+ //缓存大区
+ ParseAreaInfo(areaList)
+}
+
+// 激活服务器
+func ActiveServer(manageCenterServerAPIUrl string, serverGroupId int32) error {
+ if len(manageCenterServerAPIUrl) == 0 {
+ return fmt.Errorf("ManageCenterServerAPI地址不能为空")
+ }
+ mManageCenterServerAPIUrl = manageCenterServerAPIUrl
+
+ //定义参数
+ requestParamMap := make(map[string]string, 0)
+ requestParamMap["ServerGroupID"] = strconv.Itoa(int(serverGroupId))
+
+ //构造请求url
+ url := fmt.Sprintf("%s/%s", mManageCenterServerAPIUrl, ActivateServer_URL_SUFFIX)
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport.TLSClientConfig = &tls.Config{
+ InsecureSkipVerify: true, //关闭证书校验
+ }
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err := webUtil.PostMapData(url, requestParamMap, header, transport)
+ //statusCode, returnBytes, err := webUtil.PostMapData(url, requestParamMap, header, nil)
+ if err != nil {
+ return err
+ }
+ if statusCode != 200 {
+ return fmt.Errorf("StatusCode:%d", statusCode)
+ }
+
+ //解压缩
+ retBytes, err1 := zlibUtil.Decompress(returnBytes)
+ if err1 != nil {
+ return err1
+ }
+ // 解析返回值
+ returnObj := new(ReturnObject)
+ if err = json.Unmarshal(retBytes, &returnObj); err != nil {
+ return err
+ }
+
+ // 判断返回状态是否为成功
+ if returnObj.Code != 0 {
+ return fmt.Errorf("code:%d,Message:%s", returnObj.Code, returnObj.Message)
+ }
+
+ //解析得到的数据
+ ParseInfoFromManageCenterServer(serverGroupId, returnObj.Data.(string))
+
+ //获取白名单
+ GetWhiteListFromManageCenterServer()
+
+ //如果是初始化,则开启白名单刷新线程。避免游戏客户端刷新数据的时候重复开启线程
+ if mIsInit {
+ //启动白名单数据刷新线程
+ StartRefreshWhiteListTread()
+
+ //启动刷新MC系统配置
+ StartRefreshSysConfigTread()
+ //初始化修改为fasle
+ mIsInit = false
+ }
+
+ return nil
+}
diff --git a/.svn/pristine/0e/0e6c90a79a2d82d7163bf69aa24a408f279cd51a.svn-base b/.svn/pristine/0e/0e6c90a79a2d82d7163bf69aa24a408f279cd51a.svn-base
new file mode 100644
index 0000000..66a6829
--- /dev/null
+++ b/.svn/pristine/0e/0e6c90a79a2d82d7163bf69aa24a408f279cd51a.svn-base
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "sync"
+)
+
+type player struct {
+ // 玩家id
+ Id string `gorm:"column:Id;primary_key"`
+
+ // 玩家名称
+ Name string `gorm:"column:Name"`
+}
+
+func (this *player) resetName(name string) {
+ this.Name = name
+}
+
+func (this *player) tableName() string {
+ return "player"
+}
+
+func newPlayer(id, name string) *player {
+ return &player{
+ Id: id,
+ Name: name,
+ }
+}
+
+type playerMgr struct {
+ playerMap map[string]*player
+
+ mutex sync.Mutex
+}
+
+func (this *playerMgr) insert(obj *player) {
+ this.mutex.Lock()
+ defer this.mutex.Unlock()
+
+ this.playerMap[obj.Id] = obj
+}
+
+func (this *playerMgr) delete(obj *player) {
+ this.mutex.Lock()
+ defer this.mutex.Unlock()
+
+ delete(this.playerMap, obj.Id)
+}
+
+func (this *playerMgr) randomSelect() *player {
+ this.mutex.Lock()
+ defer this.mutex.Unlock()
+
+ for _, obj := range this.playerMap {
+ return obj
+ }
+ return nil
+}
+
+func newPlayerMgr() *playerMgr {
+ return &playerMgr{
+ playerMap: make(map[string]*player),
+ }
+}
diff --git a/.svn/pristine/0e/0ee1b8980db1cb87c67f3c144daf44fb3b086161.svn-base b/.svn/pristine/0e/0ee1b8980db1cb87c67f3c144daf44fb3b086161.svn-base
new file mode 100644
index 0000000..8a257ea
--- /dev/null
+++ b/.svn/pristine/0e/0ee1b8980db1cb87c67f3c144daf44fb3b086161.svn-base
@@ -0,0 +1,86 @@
+package bytesSendUtil
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "testing"
+ "time"
+
+ "goutil/debugUtil"
+)
+
+// 保存接收的数据用于校验
+var http_recv_msg = make([]byte, 0)
+
+func init() {
+ debugUtil.SetDebug(true)
+}
+
+type httpHandler struct {
+ cnt int
+}
+
+func (ctx *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+
+ defer r.Body.Close()
+ result, _ := ioutil.ReadAll(r.Body)
+
+ if string(result) == "http-msg-failed" {
+ http.NotFound(w, r)
+ } else {
+ ctx.cnt++
+ // 模拟一次失败
+ if ctx.cnt == 2 {
+ http.NotFound(w, r)
+ } else {
+ http_recv_msg = append(http_recv_msg, result...)
+ }
+ }
+
+}
+
+func Test_http(t *testing.T) {
+ http.Handle("/test", new(httpHandler))
+ go http.ListenAndServe("127.0.0.1:9560", nil)
+
+ httpSender, err := NewHTTPSender("./test_http", "http://127.0.0.1:9560/test")
+ if err != nil {
+ t.Error(err)
+ }
+
+ time.Sleep(time.Millisecond * 50)
+
+ // 第一次应该成功
+ httpSender.Write([]byte("http-msg-1"))
+
+ time.Sleep(time.Millisecond)
+
+ // 发送消息,此数据会多次失败,被丢弃到giveup目录
+ httpSender.Write([]byte("http-msg-failed"))
+
+ time.Sleep(time.Second * 4)
+
+ // 第二次应该失败
+ httpSender.Write([]byte("http-msg-2"))
+
+ time.Sleep(time.Millisecond)
+
+ // 保存数据
+ httpSender.Close()
+
+ // 重启之后应该会重发数据
+ httpSender, err = NewHTTPSender("./test_http", "http://127.0.0.1:9560/test")
+ if err != nil {
+ t.Error(err)
+ }
+ time.Sleep(time.Second * 2)
+
+ httpSender.Close()
+
+ if string(http_recv_msg) != "http-msg-1http-msg-2" {
+ t.Error("message error. got " + string(http_recv_msg))
+ } else {
+ fmt.Println("HTTP OK")
+ }
+}
diff --git a/.svn/pristine/0f/0f30963356a1fb59be2104ee2e958491fa209bf6.svn-base b/.svn/pristine/0f/0f30963356a1fb59be2104ee2e958491fa209bf6.svn-base
new file mode 100644
index 0000000..8036f5b
--- /dev/null
+++ b/.svn/pristine/0f/0f30963356a1fb59be2104ee2e958491fa209bf6.svn-base
@@ -0,0 +1,17 @@
+v1.0版本,支持以下功能:
+1、项目中的各种基础功能;
+2、其中的managecenterMgr兼容旧版本的ManageCenter(2019-12-01之前)。
+3、新增日志记录功能(LogMgr 2020-03-09)
+4、新增监控功能(MonitorNewMgr 2020-03-09)
+5、新增短链功能(ShortUrlMgr 2020-03-09)
+
+v2.0版本,支持以下功能:
+1、新的ManageCenter版本(2019-12-01之后)
+
+v2.0.0.1
+LogMgr里面Log日志消息先进行base64编码之后再发送到mq,因为原消息有特殊符号,
+直接发送消息会导致消息返送之后,在腾讯mq收到消息之后数据会丢失,导致验签失败
+
+v2.0.1.1
+新增屏蔽字处理forbidWordsMgr
+新增gameServerMgr
diff --git a/.svn/pristine/0f/0fe95ca68a7edc2b57740acf0aacde3feac27ecc.svn-base b/.svn/pristine/0f/0fe95ca68a7edc2b57740acf0aacde3feac27ecc.svn-base
new file mode 100644
index 0000000..869b391
--- /dev/null
+++ b/.svn/pristine/0f/0fe95ca68a7edc2b57740acf0aacde3feac27ecc.svn-base
@@ -0,0 +1,114 @@
+package coroutine_timer
+
+import (
+ "sync"
+ "testing"
+ "time"
+
+ "goutil/mathUtil"
+ "goutil/stringUtil"
+)
+
+func init() {
+}
+
+func Test_Method1(t *testing.T) {
+ imap := make(map[int]struct{})
+ var lockObj sync.Mutex
+
+ cb := func(obj interface{}) {
+ i := obj.(int)
+
+ lockObj.Lock()
+ defer lockObj.Unlock()
+
+ if _, exist := imap[i]; exist == false {
+ t.Error(i, "应该删除,不应该回调 Test_Method1")
+ }
+
+ delete(imap, i)
+ }
+
+ for i := 0; i < 20000; i++ {
+ tick := i % 20
+ isdel := false
+ if tick > 1 {
+ isdel = mathUtil.GetRand().GetRandInt(100) < 50
+ }
+ if isdel == false {
+ lockObj.Lock()
+ imap[i] = struct{}{}
+ lockObj.Unlock()
+ }
+ id := AddTimer(tick, cb, i)
+ if isdel {
+ DeleteTimer(id)
+ }
+ }
+
+ newN := 10000000
+ newId := stringUtil.GetNewUUID()
+
+ lockObj.Lock()
+ imap[newN] = struct{}{}
+ lockObj.Unlock()
+
+ err := AddTimer4(newId, 3, cb, newN)
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = AddTimer4(newId, 3, cb, newN)
+ if err == nil {
+ t.Error("未检测到重复id")
+ }
+
+ for {
+ if len(imap) == 0 {
+ break
+ }
+
+ t.Log("剩余回调次数:", len(imap))
+ time.Sleep(time.Second)
+ }
+}
+
+func Test_Method2(t *testing.T) {
+ imap := make(map[int64]struct{})
+ var lockObj sync.Mutex
+
+ cb := func(obj interface{}) {
+ i := obj.(int64)
+ n := time.Now().Unix()
+ x := n - i
+ // 此处因为启动有暂停5s,所以启动后最近的执行偏差在5s内
+ if x > 6 || x < -6 {
+ t.Errorf("错误的时间执行了回调函数 tick:%v now:%v", i, n)
+ }
+
+ lockObj.Lock()
+ defer lockObj.Unlock()
+
+ if _, exist := imap[i]; exist == false {
+ t.Error(i, "应该删除,不应该回调 Test_Method2")
+ }
+
+ delete(imap, i)
+ }
+
+ for i := 0; i < 20; i++ {
+ tick := time.Now().Unix() + int64(i)
+ imap[tick] = struct{}{}
+ AddTimer3(tick, cb, tick)
+ }
+
+ for {
+ if len(imap) == 0 {
+ break
+ }
+
+ t.Log("剩余回调次数:", len(imap))
+ time.Sleep(time.Second)
+ }
+
+}
diff --git a/.svn/pristine/10/107fc1aabad97f3332dd60150062cf10fd36945d.svn-base b/.svn/pristine/10/107fc1aabad97f3332dd60150062cf10fd36945d.svn-base
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.svn/pristine/10/107fc1aabad97f3332dd60150062cf10fd36945d.svn-base
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.svn/pristine/10/108dff723727057f2372bcb30ec7552664b06138.svn-base b/.svn/pristine/10/108dff723727057f2372bcb30ec7552664b06138.svn-base
new file mode 100644
index 0000000..195fd01
--- /dev/null
+++ b/.svn/pristine/10/108dff723727057f2372bcb30ec7552664b06138.svn-base
@@ -0,0 +1,141 @@
+package appChargeUtil
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "goutil/typeUtil"
+)
+
+// APP Store充值收据对象
+type Receipt struct {
+ // Bvrs
+ Bvrs string
+
+ // BundleIdentifier
+ BundleIdentifier string
+
+ // 产品Id
+ ProductId string
+
+ // 交易Id
+ TransactionId string
+
+ // 数量
+ Quantity int
+
+ // 状态
+ Status int
+}
+
+// BundleIdentifier是否有效
+// bundleIdentifierList:配置的BundleIdentifier列表
+// 返回值:
+// 是否有效
+func (this *Receipt) IsBundleIdentifierValid(bundleIdentifierList []string) bool {
+ for _, item := range bundleIdentifierList {
+ if this.BundleIdentifier == item {
+ return true
+ }
+ }
+
+ return false
+}
+
+// ProductId是否有效
+// productId:输入的ProductId
+// 返回值:
+// 是否有效
+func (this *Receipt) IsProductIdValid(productId string) bool {
+ return this.ProductId == productId
+}
+
+// 转换为字符串
+// 返回值:
+// 字符串
+func (this *Receipt) String() string {
+ return fmt.Sprintf("{Bvrs=%s,BundleIdentifier=%s,ProductId=%s,TransactionId=%s,Quantity=%d,Status=%d}", this.Bvrs, this.BundleIdentifier, this.ProductId, this.TransactionId, this.Quantity, this.Status)
+}
+
+// 创建新的收据对象
+// receiptInfo:收据信息
+// 返回值:
+// 收据对象
+// 错误对象
+/*
+ {
+ "receipt":
+ {
+ "original_purchase_date_pst":"2015-06-22 20:56:34 America/Los_Angeles", //购买时间,太平洋标准时间
+ "purchase_date_ms":"1435031794826", //购买时间毫秒
+ "unique_identifier":"5bcc5503dbcc886d10d09bef079dc9ab08ac11bb",//唯一标识符
+ "original_transaction_id":"1000000160390314", //原始交易ID
+ "bvrs":"1.0",//iPhone程序的版本号
+ "transaction_id":"1000000160390314", //交易的标识
+ "quantity":"1", //购买商品的数量
+ "unique_vendor_identifier":"AEEC55C0-FA41-426A-B9FC-324128342652", //开发商交易ID
+ "item_id":"1008526677",//App Store用来标识程序的字符串
+ "product_id":"cosmosbox.strikehero.gems60",//商品的标识
+ "purchase_date":"2015-06-23 03:56:34 Etc/GMT",//购买时间
+ "original_purchase_date":"2015-06-23 03:56:34 Etc/GMT", //原始购买时间
+ "purchase_date_pst":"2015-06-22 20:56:34 America/Los_Angeles",//太平洋标准时间
+ "bid":"com.cosmosbox.StrikeHero",//iPhone程序的bundle标识
+ "original_purchase_date_ms":"1435031794826"//毫秒
+ },
+ "status":0 //状态码,0为成功
+ }
+*/
+func newReceipt(receiptInfo string) (receiptObj *Receipt, err error) {
+ // 创建空对象
+ receiptObj = &Receipt{}
+
+ // 将接收的数据转化为map类型的对象
+ receiptDataMap := make(map[string]interface{})
+ err = json.Unmarshal([]byte(receiptInfo), &receiptDataMap)
+ if err != nil {
+ return
+ }
+ mapData := typeUtil.NewMapData(receiptDataMap)
+
+ // 定义、并判断返回状态
+ receiptObj.Status, err = mapData.Int("status")
+ if err != nil {
+ return
+ }
+ if receiptObj.Status != 0 {
+ err = fmt.Errorf("状态:%d不正确", receiptObj.Status)
+ return
+ }
+
+ // Receipt is actually a child
+ receiptDataMap, ok := mapData["receipt"].(map[string]interface{})
+ if !ok {
+ err = fmt.Errorf("receipt错误")
+ return
+ }
+ mapData = typeUtil.NewMapData(receiptDataMap)
+
+ // 用返回值对本对象的属性进行赋值
+ receiptObj.Bvrs, err = mapData.String("bvrs")
+ if err != nil {
+ return
+ }
+ receiptObj.BundleIdentifier, err = mapData.String("bid")
+ if err != nil {
+ return
+ }
+ receiptObj.ProductId, err = mapData.String("product_id")
+ if err != nil {
+ return
+ }
+ receiptObj.TransactionId, err = mapData.String("transaction_id")
+ if err != nil {
+ return
+ }
+ receiptObj.Quantity, err = mapData.Int("quantity")
+ if err != nil {
+ return
+ }
+
+ return
+}
diff --git a/.svn/pristine/10/10a0f5439f7d2565fa8e1274fd45c809c65da569.svn-base b/.svn/pristine/10/10a0f5439f7d2565fa8e1274fd45c809c65da569.svn-base
new file mode 100644
index 0000000..9f5ec23
--- /dev/null
+++ b/.svn/pristine/10/10a0f5439f7d2565fa8e1274fd45c809c65da569.svn-base
@@ -0,0 +1,330 @@
+package stringUtil
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "goutil/mathUtil"
+)
+
+// 使用多分隔符来进行分割(默认分隔符为:",", ";", ":", "|", "||")
+// eg:1,2;3|4||5,6;7|8||9
+// 返回值:
+// []string
+func Split(s string, seps []string) []string {
+ retList := make([]string, 0, 32)
+
+ // 如果seps为nil,则使用默认值
+ if seps == nil {
+ seps = []string{",", ";", ":", "|", "||"}
+ }
+
+ // 根据所有的分隔符来一点一点地切割字符串,直到不可切割为止
+ for {
+ startIndex := len(s) - 1
+ endIndex := 0
+ exists := false
+
+ // 遍历,找到第一个分割的位置
+ for _, sep := range seps {
+ index := strings.Index(s, sep)
+
+ // 如果找到有匹配项,则寻找最小的pos,如果有多个相同的pos,则使用长度最长的分隔符
+ if index > -1 {
+ exists = true
+
+ // 说明有多个有效的分隔符,如|和||
+ if index < startIndex {
+ startIndex = index
+ endIndex = startIndex + len(sep) - 1
+ } else if index == startIndex {
+ if startIndex+len(sep)-1 > endIndex {
+ endIndex = startIndex + len(sep) - 1
+ }
+ }
+ }
+ }
+
+ // 如果没有找到匹配的pos,则分割过程结束
+ if !exists {
+ retList = append(retList, s)
+ break
+ }
+
+ // 切割字符串
+ sub := s[:startIndex]
+ if sub != "" {
+ retList = append(retList, sub)
+ }
+ s = s[endIndex+1:]
+ }
+
+ return retList
+}
+
+// 将字符串切割为[]int
+// str:输入字符串
+// 返回值:
+// []int
+// error
+func SplitToIntSlice(s, sep string) ([]int, error) {
+ // 先按照分隔符进行切割
+ strSlice := strings.Split(s, sep)
+
+ // 定义int slice
+ intSlice := make([]int, 0, len(strSlice))
+ for _, value := range strSlice {
+ // 去除空格
+ if value = strings.TrimSpace(value); value == "" {
+ continue
+ }
+
+ if value_int, err := strconv.Atoi(value); err != nil {
+ return nil, err
+ } else {
+ intSlice = append(intSlice, value_int)
+ }
+ }
+
+ return intSlice, nil
+}
+
+// 将字符串切割为[]int32
+// s:输入字符串
+// 返回值:
+// []int
+// error
+func SplitToInt32Slice(s, sep string) ([]int32, error) {
+ // 先获得int slice
+ count := 0
+ intSlice, err := SplitToIntSlice(s, sep)
+ if err != nil {
+ return nil, err
+ } else {
+ count = len(intSlice)
+ }
+
+ // 定义int32 slice
+ int32Slice := make([]int32, 0, count)
+ for _, item := range intSlice {
+ int32Slice = append(int32Slice, int32(item))
+ }
+
+ return int32Slice, nil
+}
+
+// 将字符串切割为[]int64
+// s:输入字符串
+// 返回值:
+// []int64
+// error
+func SplitToInt64Slice(s, sep string) ([]int64, error) {
+ // 先获得int slice
+ count := 0
+ intSlice, err := SplitToIntSlice(s, sep)
+ if err != nil {
+ return nil, err
+ } else {
+ count = len(intSlice)
+ }
+
+ // 定义int32 slice
+ int64Slice := make([]int64, 0, count)
+ for _, item := range intSlice {
+ int64Slice = append(int64Slice, int64(item))
+ }
+
+ return int64Slice, nil
+}
+
+// 将字符串切割为[]float64
+// s:输入字符串
+// 返回值:
+// []float64
+// error
+func SplitToFloat64Slice(s, sep string) ([]float64, error) {
+ // 先按照分隔符进行切割
+ strSlice := strings.Split(s, sep)
+
+ // 定义float64 slice
+ floatSlice := make([]float64, 0, len(strSlice))
+ for _, value := range strSlice {
+ // 去除空格
+ if value = strings.TrimSpace(value); value == "" {
+ continue
+ }
+
+ if value_float, err := strconv.ParseFloat(value, 64); err != nil {
+ return nil, err
+ } else {
+ floatSlice = append(floatSlice, value_float)
+ }
+ }
+
+ return floatSlice, nil
+}
+
+// 将字符串切割为map[int32]int32
+// s:输入字符串
+// 返回值:
+// map[int32]float32
+// error
+func SplitToDict_KintVint(s, outerSep, innerSep string) (map[int32]int32, error) {
+ // 先按照分隔符进行切割
+ outerSlice := strings.Split(s, outerSep)
+
+ // 定义map[int32]float32
+ floatMap := make(map[int32]int32, len(outerSlice))
+ for _, itemStr := range outerSlice {
+ innerSlice := strings.Split(strings.TrimSpace(itemStr), innerSep)
+ key := strings.TrimSpace(innerSlice[0])
+ value := strings.TrimSpace(innerSlice[1])
+
+ key_int, err := strconv.Atoi(key)
+ if err != nil {
+ return nil, err
+ }
+
+ value_int, err := strconv.Atoi(value)
+ if err != nil {
+ return nil, err
+ }
+ floatMap[int32(key_int)] = int32(value_int)
+ }
+ return floatMap, nil
+}
+
+// 将字符串切割为map[int32]string
+// s:输入字符串
+// 返回值:
+// map[int32]string
+// error
+func SplitToDict_KintVstring(s, outerSep, innerSep string) (map[int32]string, error) {
+ // 先按照分隔符进行切割
+ outerSlice := strings.Split(s, outerSep)
+
+ // 定义map[int32]string
+ resultMap := make(map[int32]string, len(outerSlice))
+ for _, itemStr := range outerSlice {
+ innerSlice := strings.Split(strings.TrimSpace(itemStr), innerSep)
+ key := strings.TrimSpace(innerSlice[0])
+ value := strings.TrimSpace(innerSlice[1])
+
+ key_int, err := strconv.Atoi(key)
+ if err != nil {
+ return nil, err
+ }
+
+ resultMap[int32(key_int)] = value
+ }
+ return resultMap, nil
+}
+
+// 将字符串切割为map[int32]float32
+// s:输入字符串
+// 返回值:
+// map[int32]float32
+// error
+func SplitToDict_KintVfloat(s, outerSep, innerSep string) (map[int32]float32, error) {
+ // 先按照分隔符进行切割
+ outerSlice := strings.Split(s, outerSep)
+
+ // 定义map[int32]float32
+ floatMap := make(map[int32]float32, len(outerSlice))
+ for _, itemStr := range outerSlice {
+ innerSlice := strings.Split(strings.TrimSpace(itemStr), innerSep)
+ key := strings.TrimSpace(innerSlice[0])
+ value := strings.TrimSpace(innerSlice[1])
+
+ key_int, err := strconv.Atoi(key)
+ if err != nil {
+ return nil, err
+ }
+
+ value_float, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ return nil, err
+ }
+ floatMap[int32(key_int)] = float32(value_float)
+ }
+ return floatMap, nil
+}
+
+// 将字符串切割为map[int32]float32
+// s:输入字符串
+// 返回值:
+// map[int32]float32
+// error
+func SplitToDict_KintVfloat64(s, outerSep, innerSep string) (map[int32]float64, error) {
+ // 先按照分隔符进行切割
+ outerSlice := strings.Split(s, outerSep)
+
+ // 定义map[int32]float32
+ floatMap := make(map[int32]float64, len(outerSlice))
+ for _, itemStr := range outerSlice {
+ innerSlice := strings.Split(strings.TrimSpace(itemStr), innerSep)
+ key := strings.TrimSpace(innerSlice[0])
+ value := strings.TrimSpace(innerSlice[1])
+
+ key_int, err := strconv.Atoi(key)
+ if err != nil {
+ return nil, err
+ }
+
+ value_float, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ return nil, err
+ }
+ floatMap[int32(key_int)] = float64(value_float)
+ }
+ return floatMap, nil
+}
+
+// 将字符串切割为IntRegion列表
+// s:输入字符串,形如:1-200,201-400,401-1000
+// outerSep:外部分隔符
+// innerSep:内部分隔符
+// 返回值:
+// IntRegion列表
+// 错误对象
+func SplitToIntRegion(s, outerSep, innerSep string) (intRegionList []*mathUtil.IntRegion, err error) {
+ if s == "" {
+ err = fmt.Errorf("Input is empty")
+ return
+ }
+
+ outerRegionList := make([]string, 0, 4)
+ outerRegionList = strings.Split(s, outerSep)
+ if len(outerRegionList) == 0 {
+ err = fmt.Errorf("%s:Format invalid. Such as:1-100,101-200", s)
+ return
+ }
+
+ for _, item := range outerRegionList {
+ innerRegionList := make([]string, 0, 2)
+ innerRegionList = strings.Split(item, innerSep)
+ if len(innerRegionList) != 2 {
+ err = fmt.Errorf("%s:Format invalid. Such as:1-100", item)
+ return
+ }
+
+ var lower, upper int
+ lower, err = strconv.Atoi(innerRegionList[0])
+ if err != nil {
+ return
+ }
+ upper, err = strconv.Atoi(innerRegionList[1])
+ if err != nil {
+ return
+ }
+ if lower > upper {
+ err = fmt.Errorf("lower:%d should less than upper:%d", lower, upper)
+ return
+ }
+
+ intRegionList = append(intRegionList, mathUtil.NewIntRegion(lower, upper))
+ }
+
+ return
+}
diff --git a/.svn/pristine/11/116309fe30c7ac55d6efe3eaf1f188a4151a7571.svn-base b/.svn/pristine/11/116309fe30c7ac55d6efe3eaf1f188a4151a7571.svn-base
new file mode 100644
index 0000000..899fa1c
--- /dev/null
+++ b/.svn/pristine/11/116309fe30c7ac55d6efe3eaf1f188a4151a7571.svn-base
@@ -0,0 +1,206 @@
+// ************************************
+// @package: websocketServer
+// @description:
+// @author:
+// @revision history:
+// @create date: 2022-02-16 18:13:45
+// ************************************
+package websocketServer
+
+import (
+ "time"
+
+ "github.com/gorilla/websocket"
+ webServer "Framework/webServer"
+ logUtil "goutil/logUtil"
+)
+
+// 事件回调函数
+type EventCallbackFuncs struct {
+ // websocket连接事件
+ OnConnFunc func(ctx *Context)
+
+ // websocket关闭事件
+ OnCloseFunc func(ctx *Context)
+
+ // websocket接收事件
+ OnMsgFunc func(ctx *Context, msgType int, msgData []byte)
+}
+
+// 用户自定义数据结构
+type userDatas struct {
+ // WsServer 或 WssServer 指针
+ server interface{}
+
+ // 事件回调函数
+ eventCallback *EventCallbackFuncs
+}
+
+// iServerMgr
+// @description: WsServer/WssServer内部管理接口,以便hookHandler中统一访问
+type iServerMgr interface {
+ // 升级为websocket
+ upgrade(ctx *Context) (conn *websocket.Conn, err error)
+
+ // 将连接从连接池删除
+ delConn(conn *websocket.Conn)
+
+ // 获取接收到Ping消息时,是否自动回复Pong信息
+ GetAutoPong() bool
+}
+
+// 回调勾子,将http/https升级为websocket
+func hookHandler(webServerCtx *webServer.Context) {
+ defer func() {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+ }
+ }()
+
+ userDataI := webServerCtx.GetUserData()
+ if userDataI == nil {
+ return
+ }
+
+ userData, ok := userDataI.(*userDatas)
+ if !ok {
+ logUtil.ErrorLog("userData type error")
+ return
+ }
+
+ // 通信结束信号
+ cls := make(chan struct{})
+ ctx := &Context{
+ webServerCtx: webServerCtx, // web_server环境
+ cls: cls, // 关闭连接信号
+ }
+
+ var serverMgr iServerMgr
+ var conn *websocket.Conn
+ var err error
+
+ // 转为iServerMgr
+ switch userData.server.(type) {
+ case *WsServer:
+ if svr, ok := userData.server.(*WsServer); ok {
+ serverMgr = svr
+ } else {
+ logUtil.ErrorLog("server type not WsServer")
+ return
+ }
+ case *WssServer:
+ if svr, ok := userData.server.(*WssServer); ok {
+ serverMgr = svr
+ } else {
+ logUtil.ErrorLog("server type not WssServer")
+ return
+ }
+ default:
+ logUtil.ErrorLog("server type not WsServer or WssServer")
+ return
+ }
+
+ // 升级为websocket
+ conn, err = serverMgr.upgrade(ctx)
+ if err != nil {
+ if err.Error() == "connManager(disableNewConn)" {
+ // 禁用新连接。正常功能,直接返回
+ return
+ }
+
+ logUtil.ErrorLog("websocket Upgrade failed: %v", err)
+ return
+ }
+
+ // 将连接从连接池删除
+ defer serverMgr.delConn(conn)
+
+ // 关闭连接
+ defer conn.Close()
+
+ // 默认情况下,ReadMessage不会读取到ping/pong/close消息(内部有专门的处理函数)
+ // 设置心跳包处理函数
+ conn.SetPingHandler(func(msg string) error {
+ // 只要收到消息,都需要更新最近一次收到心跳包的时间
+ ctx.heartbeat = time.Now()
+
+ if serverMgr.GetAutoPong() {
+ // 自动回应一个Pong心跳
+ go ctx.SendMessage(websocket.PongMessage, []byte(msg))
+ }
+
+ // 接收消息回调
+ if userData.eventCallback.OnMsgFunc != nil {
+ userData.eventCallback.OnMsgFunc(ctx, websocket.PingMessage, []byte(msg))
+ }
+
+ return nil
+ })
+ // 设置关闭包处理函数
+ conn.SetCloseHandler(func(code int, text string) error {
+ // 所有向cls写入,都使用select超时结构,以保证这儿不会一直阻塞,确保此协程能退出
+ select {
+ case <-time.After(time.Millisecond * 10):
+ case cls <- struct{}{}:
+ }
+ return nil
+ })
+
+ // 设置最近一次收到心跳包的时间
+ ctx.heartbeat = time.Now()
+
+ // 新连接回调
+ if userData.eventCallback.OnConnFunc != nil {
+ userData.eventCallback.OnConnFunc(ctx)
+ }
+
+ // 开启读协程
+ go func() {
+ defer func() {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+
+ // 有异常出现(可能是用户回调中出现异常);执行到这儿,需要关闭连接
+ // 所有向cls写入,都使用select超时结构,以保证这儿不会一直阻塞,确保此协程能退出
+ select {
+ case <-time.After(time.Millisecond * 10):
+ case cls <- struct{}{}:
+ }
+ }
+ }()
+
+ for {
+ // 注意:ReadMessage不会读取到心跳包和关闭包数据;心跳包/关闭包需要设置专门的处理函数
+ // 但内部对心跳包/关闭包的处理,也是由ReadMessage函数触发的(也就是不调用ReadMessage函数,可能也不会触发对心跳包/关闭包的处理);
+ // 经测试和内部代码确认:调用心跳包/关闭包处理函数时,ReadMessage不会返回;心跳包/关闭包处理函数调用完毕后ReadMessage才可能返回
+ mt, msg, err := conn.ReadMessage()
+ if err != nil {
+ // 所有向cls写入,都使用select超时结构,以保证这儿不会一直阻塞,确保此协程能退出
+ select {
+ case <-time.After(time.Millisecond * 10):
+ case cls <- struct{}{}:
+ }
+ break
+ }
+
+ // 只要收到消息,都需要更新最近一次收到心跳包的时间
+ ctx.heartbeat = time.Now()
+
+ // 接收消息回调
+ if userData.eventCallback.OnMsgFunc != nil {
+ userData.eventCallback.OnMsgFunc(ctx, mt, msg)
+ }
+ }
+ }()
+
+ // 等待退出
+ <-cls
+
+ // 设置已关闭标志
+ ctx.isClosed = true
+
+ // 关闭回调
+ if userData.eventCallback.OnCloseFunc != nil {
+ userData.eventCallback.OnCloseFunc(ctx)
+ }
+}
diff --git a/.svn/pristine/11/11dd611238f6e4771bc74430cc3f2bee6b274238.svn-base b/.svn/pristine/11/11dd611238f6e4771bc74430cc3f2bee6b274238.svn-base
new file mode 100644
index 0000000..e8434bb
--- /dev/null
+++ b/.svn/pristine/11/11dd611238f6e4771bc74430cc3f2bee6b274238.svn-base
@@ -0,0 +1,109 @@
+/*
+请求结构简介
+最近更新时间:2019-08-01 19:14:44
+
+编辑 查看pdf
+在这篇文章中:
+服务地址
+通信协议
+请求方法
+请求参数
+字符编码
+对腾讯云的 API 接口的调用是通过向腾讯云 API 的服务端地址发送请求,并按照接口说明在请求中加入相应的请求参数来完成的。腾讯云 API 的请求结构由:服务地址、通信协议、请求方法、请求参数和字符编码组成。具体描述如下:
+
+服务地址
+腾讯云 API 的服务接入地址与具体模块相关,详细请参见各接口相关描述。
+
+通信协议
+腾讯云 API 的大部分接口都通过 HTTPS 进行通信,为您提供高安全性的通信通道。
+
+请求方法
+腾讯云 API 同时支持 POST 和 GET 请求。
+
+注意:
+
+POST 和 GET 请求不能混合使用,若使用 GET 方式,则参数均从 Querystring 取得;
+若使用 POST 方式,则参数均从 Request Body 中取得,而 Querystring 中的参数将忽略。
+两种请求方式的参数格式规则相同,一般情况下使用 GET 请求,当参数字符串过长时推荐使用 POST。
+如果用户的请求方法是 GET,则对所有请求参数值均需要做 URL 编码,若为 POST,则无需对参数编码。
+GET 请求的最大长度根据不同的浏览器和服务器设置有所不同,例如,传统 IE 浏览器限制为 2K,Firefox 限制为 8K;对于一些参数较多、长度较长的 API 请求,建议您使用 POST 方法以免在请求过程中会由于字符串超过最大长度而导致请求失败。
+对于 POST 请求,您需要使用 x-www-form-urlencoded 的形式传参,因为云 API 侧是从 $_POST 中取出请求参数的。
+请求参数
+腾讯云 API 的每个请求都需要指定两类参数:公共请求参数以及接口请求参数。其中公共请求参数是每个接口都要用到的请求参数,具体可参见 公共请求参数,而接口请求参数是各个接口所特有的,具体见各个接口的“请求参数”描述。
+
+字符编码
+腾讯云 API 的请求及返回结果均使用 UTF-8 字符集进行编码。
+*/
+package model
+
+import (
+ "fmt"
+ "time"
+
+ "goutil/mathUtil"
+)
+
+// CommonRequest 公共请求参数对象
+type CommonRequest struct {
+ // Action 指令接口名称(必须)
+ Action string
+
+ // 地域参数(必须)
+ Region string
+
+ // Timestamp 当前UNIX时间戳(必须)
+ Timestamp uint64
+
+ // Nonce 随机正整数(必须)
+ Nonce uint32
+
+ // SecretId 在云API密钥上申请的标识身份的SecretId(必须)
+ SecretId string
+
+ // 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。
+ Signature string
+
+ // 签名方式,目前支持 HmacSHA256 和 HmacSHA1。只有指定此参数为 HmacSHA256 时,才使用 HmacSHA256 算法验证签名,其他情况均使用 HmacSHA1 验证签名。
+ SignatureMethod string
+
+ // 队列名称(此属性虽然不是API文档中的公共属性,但是在队列模型中确实事实上的公共属性,所以将其转移到此处)
+ queueName string
+}
+
+// AssembleParamMap 组装请求参数字典
+// 返回值
+// map[string]interface{}:请求参数字
+func (this *CommonRequest) AssembleParamMap() map[string]string {
+ result := make(map[string]string)
+
+ // 组装参数
+ result["Action"] = this.Action
+ result["Region"] = this.Region
+ result["Timestamp"] = fmt.Sprintf("%d", this.Timestamp)
+ result["Nonce"] = fmt.Sprintf("%d", this.Nonce)
+ result["SecretId"] = this.SecretId
+ result["SignatureMethod"] = this.SignatureMethod
+ result["queueName"] = this.queueName
+
+ return result
+}
+
+// NewCommonRequest 新建公共请求参数对象
+// 参数
+// action:指令接口名称
+// region:地域
+// secretId:在云API密钥上申请的标识身份的SecretId
+// queueName:队列名称
+// 返回值
+// *CommonRequest:公共请求参数对象
+func NewCommonRequest(action, region, secretId, queueName string) *CommonRequest {
+ return &CommonRequest{
+ Action: action,
+ Region: region,
+ Timestamp: uint64(time.Now().Unix()),
+ Nonce: mathUtil.GetRand().Uint32(),
+ SecretId: secretId,
+ SignatureMethod: "HmacSHA256",
+ queueName: queueName,
+ }
+}
diff --git a/.svn/pristine/11/11ea234943ccae37879b6dbde2815a17b6504038.svn-base b/.svn/pristine/11/11ea234943ccae37879b6dbde2815a17b6504038.svn-base
new file mode 100644
index 0000000..d7b4053
--- /dev/null
+++ b/.svn/pristine/11/11ea234943ccae37879b6dbde2815a17b6504038.svn-base
@@ -0,0 +1,61 @@
+package configYaml
+
+import (
+ "framework/configMgr"
+ "gopkg.in/yaml.v3"
+ "goutil/logUtil"
+ "goutil/yamlUtil"
+ "log"
+)
+
+var (
+ // 配置对象
+
+ configManager = configMgr.NewConfigManager()
+)
+
+// init
+//
+// @description: init
+//
+// parameter:
+// return:
+func init() {
+ // 设置日志文件的存储目录
+ logUtil.SetLogPath("LOG")
+
+ if err := reloadConfig(); err != nil {
+ panic(err)
+ }
+
+ //加载配置
+ initBaseConfig()
+ initDbConfig()
+ initFunctionConfig()
+ initLogMgrConfig()
+}
+
+// reloadConfig
+//
+// @description: reloadConfig
+//
+// parameter:
+// return:
+//
+// @error: 错误信息
+func reloadConfig() error {
+
+ yamlFile, err := yamlUtil.LoadFromFile("config.yaml")
+ if err != nil {
+ return err
+ }
+
+ // 解析 YAML 文件
+ err = yaml.Unmarshal(yamlFile, &ConfigYaml)
+ if err != nil {
+ log.Fatalf("Error unmarshalling config file: %v", err)
+ return err
+ }
+
+ return nil
+}
diff --git a/.svn/pristine/11/11f624645ee771a7b2811130a3b416d486e6e892.svn-base b/.svn/pristine/11/11f624645ee771a7b2811130a3b416d486e6e892.svn-base
new file mode 100644
index 0000000..422b34c
--- /dev/null
+++ b/.svn/pristine/11/11f624645ee771a7b2811130a3b416d486e6e892.svn-base
@@ -0,0 +1,71 @@
+package webUtil
+
+import (
+ "testing"
+ "time"
+)
+
+func TestGet(t *testing.T) {
+ client := NewClient(nil)
+
+ result, err := client.Get("https://www.baidu.com", nil)
+ if err != nil {
+ t.Errorf("测试错误,返回的结果为:%s", err)
+ }
+
+ if len(result) == 0 {
+ t.Errorf("返回的数据为空,期望不为空")
+ }
+
+ //t.Log(string(result))
+}
+
+func TestGetTimeout(t *testing.T) {
+ transportOPT := &TransportOPT{
+ Timeout: 3 * time.Second,
+ }
+ opt := make(map[string]interface{})
+ opt["Timeout"] = 3 * time.Second
+
+ client := NewClient(transportOPT)
+ _, err := client.Get("https://www.google.com", nil)
+ if err != nil {
+ t.Log(err)
+ return
+ }
+
+ t.Errorf("测试异常")
+}
+
+func TestPostWithMap(t *testing.T) {
+ client := NewClient(nil)
+
+ data := make(map[string]string)
+ data["test1"] = "value1"
+ data["test2"] = "value2"
+ result, err := client.PostWithMap("http://www.baidu.com", data, nil)
+ if err != nil {
+ t.Errorf("测试错误,返回的结果为:%s", err)
+ }
+
+ if len(result) == 0 {
+ t.Errorf("返回的数据为空,期望不为空")
+ }
+
+ //t.Log(string(result))
+}
+
+func TestPostWithByte(t *testing.T) {
+ client := NewClient(nil)
+
+ result, err := client.PostWithByte("http://www.baidu.com", []byte("test=abc"), nil)
+ if err != nil {
+ t.Errorf("测试错误,返回的结果为:%s", err)
+ }
+
+ if len(result) == 0 {
+ t.Errorf("返回的数据为空,期望不为空")
+ }
+
+ //t.Log(string(result))
+}
diff --git a/.svn/pristine/12/12d698470913bfc03a551aa87944abac426b9072.svn-base b/.svn/pristine/12/12d698470913bfc03a551aa87944abac426b9072.svn-base
new file mode 100644
index 0000000..f5c8059
--- /dev/null
+++ b/.svn/pristine/12/12d698470913bfc03a551aa87944abac426b9072.svn-base
@@ -0,0 +1,13 @@
+package qcloud
+
+type telField struct {
+ Nationcode string `json:"nationcode"`
+ Mobile string `json:"mobile"`
+}
+
+func newTelField(nation, mobile string) *telField {
+ return &telField{
+ Nationcode: nation,
+ Mobile: mobile,
+ }
+}
diff --git a/.svn/pristine/12/12f5e440c04874ab483587453f0e175feeb4c956.svn-base b/.svn/pristine/12/12f5e440c04874ab483587453f0e175feeb4c956.svn-base
new file mode 100644
index 0000000..d7d8f9b
--- /dev/null
+++ b/.svn/pristine/12/12f5e440c04874ab483587453f0e175feeb4c956.svn-base
@@ -0,0 +1,105 @@
+package gameServerMgr
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "time"
+
+ "Framework/goroutineMgr"
+ . "Framework/managecenterModel"
+ "goutil/logUtil"
+ "goutil/webUtil"
+)
+
+const SYSCONF_URL_SUFFIX string = "/API/SysConfig.ashx"
+
+var (
+ mSysConfig *SysConfig
+)
+
+// 获取MC系统配置
+func GetSysConfigFromManageCenterServer() error {
+ //定义参数
+ requestParamMap := make(map[string]string, 0)
+ requestParamMap["IsResultCompressed"] = "false"
+
+ //构造url
+ url := fmt.Sprintf("%s/%s", mManageCenterServerAPIUrl, SYSCONF_URL_SUFFIX)
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err := webUtil.PostMapData(url, requestParamMap, header, transport)
+ //statusCode, returnBytes, err := webUtil.PostMapData(url, requestParamMap, header, nil)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取MC系统配置出错,url:%s,错误信息为:%s", url, err))
+ return err
+ }
+ if statusCode != 200 {
+ logUtil.ErrorLog(fmt.Sprintf("获取MC系统配置出错,url:%s,错误码为:%d", url, statusCode))
+ return err
+ }
+ // 解析返回值
+ returnObj := new(ReturnObject)
+ if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取MC系统配置出错,反序列化返回值出错,错误信息为:%s, str:%s", err, string(returnBytes)))
+ return err
+ }
+
+ // 判断返回状态是否为成功
+ if returnObj.Code != 0 {
+ // 数据没有变化,所以没有获取到新的数据,不能算错误。
+ if returnObj.Code == 47 || returnObj.Message == "DataNotChanged" {
+ return nil
+ } else {
+ msg := fmt.Sprintf("获取MC系统配置出错,返回状态:%d,信息为:%s", returnObj.Code, returnObj.Message)
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ }
+ }
+
+ // 解析Data
+ var tmpSysConfig *SysConfig
+ if data, ok := returnObj.Data.(string); !ok {
+ msg := "获取MC系统配置出错,返回的数据不是string类型"
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ } else {
+ if err = json.Unmarshal([]byte(data), &tmpSysConfig); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取MC系统配置出错出错,反序列化数据出错,错误信息为:%s", err))
+ return err
+ }
+ }
+
+ // 赋值给最终的sysconfig
+ mSysConfig = tmpSysConfig
+
+ return nil
+}
+
+// 定时刷新MC系统配置
+func StartRefreshSysConfigTread() {
+ // 定时刷新数据
+ go func() {
+ goroutineName := "gameServerMgr.StartRefreshSysConfigTread"
+ goroutineMgr.Monitor(goroutineName)
+ defer goroutineMgr.ReleaseMonitor(goroutineName)
+
+ for {
+ // 每30秒刷新一次
+ time.Sleep(30 * time.Second)
+
+ // MC系统配置
+ GetSysConfigFromManageCenterServer()
+ }
+ }()
+}
+
+// 获取系统配置
+func GetSysConfig() *SysConfig {
+ return mSysConfig
+}
diff --git a/.svn/pristine/12/12f75adbec35d99e08a5f0ff52f0c36225adff02.svn-base b/.svn/pristine/12/12f75adbec35d99e08a5f0ff52f0c36225adff02.svn-base
new file mode 100644
index 0000000..12de232
--- /dev/null
+++ b/.svn/pristine/12/12f75adbec35d99e08a5f0ff52f0c36225adff02.svn-base
@@ -0,0 +1,54 @@
+package initMgr
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestRegister(t *testing.T) {
+ Register("first", 1, first)
+ Register("second", 2, second)
+ Register("third", 3, third)
+ Register("fourth", 4, fourth)
+}
+
+func TestCallOne(t *testing.T) {
+ name := "first"
+ if err := CallOne(name); err != nil {
+ t.Errorf("there should be no error, but now it has:%s", err)
+ }
+}
+
+func TestCallAny(t *testing.T) {
+ errList := CallAny("second", "third")
+ if len(errList) != 1 {
+ t.Errorf("there should be 1 error, but now:%d", len(errList))
+ }
+}
+
+func TestCallAll(t *testing.T) {
+ errList := CallAll()
+ if len(errList) != 2 {
+ t.Errorf("there should be 1 error, but now:%d", len(errList))
+ }
+}
+
+func first() error {
+ fmt.Println("first")
+ return nil
+}
+
+func second() error {
+ fmt.Println("second")
+ return fmt.Errorf("the second error")
+}
+
+func third() error {
+ fmt.Println("third")
+ return nil
+}
+
+func fourth() error {
+ fmt.Println("fourth")
+ return fmt.Errorf("the fourth error")
+}
diff --git a/.svn/pristine/12/12fec7f3f1013e25716d622f56b3972e13598eea.svn-base b/.svn/pristine/12/12fec7f3f1013e25716d622f56b3972e13598eea.svn-base
new file mode 100644
index 0000000..0e03193
--- /dev/null
+++ b/.svn/pristine/12/12fec7f3f1013e25716d622f56b3972e13598eea.svn-base
@@ -0,0 +1,89 @@
+package user
+
+import (
+ "common/cache"
+ "common/connection"
+ "goutil/logUtilPlus"
+ "sync"
+)
+
+// 用户缓存对象
+var userMap = make(map[int64]*User)
+var rwmu sync.RWMutex
+
+// GetUserByID 根据用户id获取用户信息
+func GetUserByID(UserID int64) (*User, error) {
+
+ //判断缓存是否存在
+ var user *User
+
+ func() *User {
+ rwmu.RLock()
+ defer rwmu.RUnlock()
+ ok := true
+ if user, ok = userMap[UserID]; ok {
+ return user
+ }
+ return nil
+ }()
+
+ if user != nil {
+ return user, nil
+ }
+
+ result := connection.GetUserDB().First(&user, UserID)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+
+ //添加缓存
+ func() {
+ rwmu.Lock()
+ defer rwmu.Unlock()
+ user.Cache = cache.NewCache()
+ userMap[user.ID] = user
+ }()
+
+ return user, nil
+}
+
+// AddUserCache 添加用户缓存
+func AddUserCache(user *User) {
+ rwmu.Lock()
+ defer rwmu.Unlock()
+ user.Cache = cache.NewCache()
+ userMap[user.ID] = user
+}
+
+// AddUser 添加用户
+// AddUser 添加新的用户到数据库中。
+// 参数 User: 包含用户信息的对象。
+// 返回值: 插入操作影响的行数和可能发生的错误。
+func AddUser(User *User) (int64, error) {
+
+ //处理一些验证
+
+ //写入缓存
+ AddUserCache(User)
+
+ // 写入到数据库
+ result := connection.GetUserDB().Create(&User) // 通过数据的指针来创建
+
+ if result.Error != nil {
+ logUtilPlus.ErrorLog("添加用户失败 错误信息:", result.Error.Error())
+ }
+ return User.ID, nil
+}
+
+// Login 用户登录
+func Login(account string, password string) (*User, error) {
+
+ //这里优先验证缓存数据
+
+ var User User
+ result := connection.GetUserDB().Where("account = ? AND password = ?", account, password).First(&User)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+ return &User, nil
+}
diff --git a/.svn/pristine/13/133b571edb1ebc33483b575fba2f0df647af9e8a.svn-base b/.svn/pristine/13/133b571edb1ebc33483b575fba2f0df647af9e8a.svn-base
new file mode 100644
index 0000000..6012895
--- /dev/null
+++ b/.svn/pristine/13/133b571edb1ebc33483b575fba2f0df647af9e8a.svn-base
@@ -0,0 +1,20 @@
+
+
+
+ 这里有中文哦
+
+
+
+ This is a H1
+
+
+ Hello,This is an example for gxpath.
+
+
+
+
\ No newline at end of file
diff --git a/.svn/pristine/13/13a7a5172d7c0e0fdc2fe718e7d1e71f371e8ac6.svn-base b/.svn/pristine/13/13a7a5172d7c0e0fdc2fe718e7d1e71f371e8ac6.svn-base
new file mode 100644
index 0000000..8583cf6
--- /dev/null
+++ b/.svn/pristine/13/13a7a5172d7c0e0fdc2fe718e7d1e71f371e8ac6.svn-base
@@ -0,0 +1,76 @@
+package monitorNewMgr
+
+import (
+ "time"
+)
+
+//服务器节点信息
+type ServerNodeMessage struct {
+ //通用信息
+ CommInfo CommInfoModel
+
+ // indexMap 指标对象
+ IndexSlice []Index
+}
+
+type Index struct {
+ // IndexName 指标名字(eg:可以为cpu,mem,numGoroutine,proxy)
+ IndexName string
+
+ // moduleName 模块名字
+ ModuleName string
+
+ // methodName 方法名字
+ MethodName string
+
+ // value 指标值(eg:indexName为cpu时,value 为cpu使用率,indexName为内存时,value为内存使用率)
+ Value float64
+}
+
+//服务监控中心信息
+type MonitorCenterMessage struct {
+ //通用信息
+ CommInfo CommInfoModel
+
+ // Cpu 核数
+ Cpu int32
+
+ // Mem 内存大小
+ Mem int32
+
+ // Status
+ Status int32
+}
+
+// 通用信息
+type CommInfoModel struct {
+ // 项目组ID
+ GroupId string
+
+ // projectId 项目Id (eg:迪士尼)
+ ProjectId string
+
+ // clusterId 集群Id(一个集群相当于一个大区)
+ ClusterId string
+
+ // 组密钥
+ ProjectSecret string
+
+ // 服务器IP
+ IP string
+
+ // Port 服务端口
+ Port int32
+
+ // 服务名(eg:玩家服务player,城市服务:city,代理服务:proxy)
+ ServiceName string
+
+ // instanceId 服务实例Id
+ InstanceId string
+
+ // tll 时间戳
+ Tll time.Duration
+
+ // 签名
+ Sign string
+}
diff --git a/.svn/pristine/14/14de84ff1959026fcd250504d7000e59f58e3b41.svn-base b/.svn/pristine/14/14de84ff1959026fcd250504d7000e59f58e3b41.svn-base
new file mode 100644
index 0000000..b77992c
--- /dev/null
+++ b/.svn/pristine/14/14de84ff1959026fcd250504d7000e59f58e3b41.svn-base
@@ -0,0 +1,53 @@
+package configUtil
+
+import (
+ "testing"
+)
+
+var (
+ config map[string]interface{}
+ err error
+)
+
+func TestReadJsonConfig(t *testing.T) {
+ config, err = ReadJsonConfig("testdata/jsonConfig.ini")
+ if err != nil {
+ t.Errorf("读取JSON配置失败,错误信息为:%s", err)
+ }
+}
+
+func TestReadIntJsonValue(t *testing.T) {
+ actualValue, err := ReadIntJsonValue(config, "ServerGroupId")
+ if err != nil {
+ t.Errorf("读取JSON配置失败,错误信息为:%s", err)
+ }
+
+ expectedValue := 1
+ if actualValue != expectedValue {
+ t.Errorf("期望的值为%d,实际的值为%d", expectedValue, actualValue)
+ }
+}
+
+func TestReadStringJsonValue(t *testing.T) {
+ actualValue, err := ReadStringJsonValue(config, "ChatDBConnection")
+ if err != nil {
+ t.Errorf("读取JSON配置失败,错误信息为:%s", err)
+ }
+
+ expectedValue := "root:moqikaka@tcp(192.168.1.226:3306)/chatserver?charset=utf8&parseTime=true&loc=Local&timeout=30s"
+ if actualValue != expectedValue {
+ t.Errorf("期望的值为%s,实际的值为%s", expectedValue, actualValue)
+ }
+}
+
+func TestReadBoolJsonValue(t *testing.T) {
+ actualValue, err := ReadBoolJsonValue(config, "IfRecordMessage")
+ if err != nil {
+ t.Errorf("读取JSON配置失败,错误信息为:%s", err)
+ }
+
+ expectedValue := true
+ if actualValue != expectedValue {
+ t.Errorf("期望的值为%v,实际的值为%v", expectedValue, actualValue)
+ }
+}
diff --git a/.svn/pristine/14/14f1b3374c1cb8cdd4b7ad9f7efe545734fe2675.svn-base b/.svn/pristine/14/14f1b3374c1cb8cdd4b7ad9f7efe545734fe2675.svn-base
new file mode 100644
index 0000000..92f898c
--- /dev/null
+++ b/.svn/pristine/14/14f1b3374c1cb8cdd4b7ad9f7efe545734fe2675.svn-base
@@ -0,0 +1,127 @@
+package logUtil
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+const (
+ con_MIN_SKIP = 1
+ con_MAX_SKIP = 10
+)
+
+// InfoLog 信息日志记录
+// format:日志格式
+// args:参数列表
+func InfoLog(format string, args ...interface{}) {
+ for _, log := range logs {
+ log.InfoLog(format, args...)
+ }
+}
+
+// WarnLog 警告日志记录
+// format:日志格式
+// args:参数列表
+func WarnLog(format string, args ...interface{}) {
+ for _, log := range logs {
+ log.WarnLog(format, args...)
+ }
+}
+
+// DebugLog 调试日志记录
+// format:日志格式
+// args:参数列表
+func DebugLog(format string, args ...interface{}) {
+ for _, log := range logs {
+ log.DebugLog(format, args...)
+ }
+}
+
+// ErrorLog 错误日志记录
+// format:日志格式
+// args:参数列表
+func ErrorLog(format string, args ...interface{}) {
+ for _, log := range logs {
+ log.ErrorLog(format, args...)
+ }
+}
+
+// FatalLog 致命错误日志记录
+// format:日志格式
+// args:参数列表
+func FatalLog(format string, args ...interface{}) {
+ for _, log := range logs {
+ log.FatalLog(format, args...)
+ }
+}
+
+// Close
+// @description: 关闭日志
+// parameter:
+// @waitFinish:是否等待关闭完成
+// return:
+func Close(waitFinish bool) {
+ for _, log := range logs {
+ log.CloseLog(waitFinish)
+ }
+}
+
+//--------------------------Deprecated methods start----------------------------
+
+// Log 日志记录
+// Deprecated: use XXXLog api instead
+func Log(logInfo string, lv LogType, ifIncludeHour bool) {
+ switch lv {
+ case Info:
+ InfoLog(logInfo)
+ case Warn:
+ WarnLog(logInfo)
+ case Debug:
+ DebugLog(logInfo)
+ case Error:
+ ErrorLog(logInfo)
+ case Fatal:
+ FatalLog(logInfo)
+ }
+}
+
+// NormalLog 日志记录
+// Deprecated: use XXXLog api instead
+func NormalLog(logInfo string, level LogType) {
+ Log(logInfo, level, true)
+}
+
+// LogAndPrint 日志记录
+// Deprecated: use XXXLog api instead
+func LogAndPrint(logInfo string, level LogType) {
+ NormalLog(logInfo, level)
+ fmt.Println(logInfo)
+}
+
+// LogUnknownError 日志记录
+func LogUnknownError(r interface{}, args ...string) {
+ buf := strings.Builder{}
+ buf.WriteString(fmt.Sprintf("通过recover捕捉到的未处理异常:%v \n", r))
+
+ // 获取附加信息
+ if len(args) > 0 {
+ buf.WriteString("附加信息:")
+ buf.WriteString(strings.Join(args, "-"))
+ buf.WriteString("\n")
+ }
+
+ // 获取堆栈信息
+ for skip := con_MIN_SKIP; skip <= con_MAX_SKIP; skip++ {
+ _, file, line, ok := runtime.Caller(skip)
+ if !ok {
+ break
+ }
+ buf.WriteString(fmt.Sprintf("skip = %d, file = %s, line = %d \n", skip, file, line))
+ buf.WriteString("\n")
+ }
+
+ ErrorLog(buf.String())
+}
+
+//--------------------------Deprecated methods end----------------------------
diff --git a/.svn/pristine/15/15c0d6e3d729f98b5b8564f2033328f4aee93dc0.svn-base b/.svn/pristine/15/15c0d6e3d729f98b5b8564f2033328f4aee93dc0.svn-base
new file mode 100644
index 0000000..941f258
--- /dev/null
+++ b/.svn/pristine/15/15c0d6e3d729f98b5b8564f2033328f4aee93dc0.svn-base
@@ -0,0 +1,76 @@
+// ************************************
+// @package: websocketServer
+// @description: WsServer/WssServer接口,以便统一调用
+// @author:
+// @revision history:
+// @create date: 2022-02-22 16:07:27
+// ************************************
+package websocketServer
+
+import (
+ "github.com/gorilla/websocket"
+ webServer "Framework/webServer"
+ "sync"
+ "time"
+)
+
+// IServer
+// @description: WsServer/WssServer接口,以便统一调用
+type IServer interface {
+ //-------------------------------------
+ // HttpServer方法
+
+ // HttpServer接口
+ webServer.IWebServer
+
+ // 设置地址
+ SetAddr(addr string)
+
+ // 启动HttpServer
+ Start(wg *sync.WaitGroup)
+
+ //-------------------------------------
+ // websocket方法
+
+ // 注册websocket回调
+ RegisterWebsocketHandler(path string, eventCallback *EventCallbackFuncs, configObj *webServer.HandlerConfig)
+
+ // 注册正则websocket回调
+ RegisterRegexWebsocketHandler(path string, eventCallback *EventCallbackFuncs, configObj *webServer.HandlerConfig)
+
+ // 设置websocket参数结构
+ SetUpgrader(upgrader *websocket.Upgrader)
+
+ // 获取websocket参数结构
+ GetUpgrader() *websocket.Upgrader
+
+ // 设置接收到Ping消息时,是否自动回复Pong信息
+ SetAutoPong(autuPong bool)
+
+ // 获取接收到Ping消息时,是否自动回复Pong信息
+ GetAutoPong() bool
+
+ // 设置心跳检测信息
+ SetHeartbeatDetectInfo(heartbeatCloseCount int, heartbeatCycle time.Duration)
+
+ // 获取心跳检测信息
+ GetHeartbeatDetectInfo() (heartbeatCloseCount int, heartbeatCycle time.Duration)
+
+ // 设置广播并发数
+ SetBroadcastConcurrent(n int)
+
+ // 允许新连接
+ EnableNewConn()
+
+ // 禁用新连接
+ DisableNewConn()
+
+ // 多播消息(给指定多用户发送消息)
+ MulticastMessage(ctxs []*Context, messageType int, data []byte) (err error)
+
+ // 消息广播
+ BroadcastMessage(messageType int, data []byte) (err error)
+
+ // 关闭所有连接
+ CloseAll()
+}
diff --git a/.svn/pristine/16/1651822b5dae47034a6e1eca1f65ebcdd985ab61.svn-base b/.svn/pristine/16/1651822b5dae47034a6e1eca1f65ebcdd985ab61.svn-base
new file mode 100644
index 0000000..3a4043c
--- /dev/null
+++ b/.svn/pristine/16/1651822b5dae47034a6e1eca1f65ebcdd985ab61.svn-base
@@ -0,0 +1,80 @@
+
+
+
+ go websocket
+
+
+
+
+ WebSocket Test
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.svn/pristine/17/175c67ad8c4ec0d0b345954e5fcd054c655fcda7.svn-base b/.svn/pristine/17/175c67ad8c4ec0d0b345954e5fcd054c655fcda7.svn-base
new file mode 100644
index 0000000..e7496b7
--- /dev/null
+++ b/.svn/pristine/17/175c67ad8c4ec0d0b345954e5fcd054c655fcda7.svn-base
@@ -0,0 +1,15 @@
+package dfaExUtil
+
+import "testing"
+
+func TestHandleWord(t *testing.T) {
+ strs := []string{"ABC", "1234", "测试", "测试代码", "测试一下"}
+
+ dfaEx1 := NewDFAEx(strs)
+ str := dfaEx1.HandleWord("abc按了数字12345来测试代码是否正常,结果测试出了bug", '*')
+ t.Log(str)
+
+ dfaEx2 := NewDFAEx(strs, true)
+ str = dfaEx2.HandleWord("abc按了数字12345来测试代码是否正常,结果测试出了bug", '*')
+ t.Log(str)
+}
diff --git a/.svn/pristine/17/17893865ee184352bf16c2e23e049560a9b6ba80.svn-base b/.svn/pristine/17/17893865ee184352bf16c2e23e049560a9b6ba80.svn-base
new file mode 100644
index 0000000..c8ecf86
--- /dev/null
+++ b/.svn/pristine/17/17893865ee184352bf16c2e23e049560a9b6ba80.svn-base
@@ -0,0 +1,93 @@
+/*
+提供统一的ip验证的逻辑;包括两部分:
+1、ManageCenter中配置到ServerGroup中的IP;系统内部自动处理,外部无需关注(暂时不用);
+2、各个应用程序中配置的ip;通过调用Init或InitString方法进行初始化;
+*/
+package ipMgr
+
+import (
+ "sync"
+
+ "goutil/stringUtil"
+)
+
+var (
+ ipMap = make(map[string]struct{}, 32) // 本地ip集合
+ ipCheckFuncList = make([]func(string) bool, 0, 16) // ip检查函数列表
+ mutex sync.RWMutex
+)
+
+// 初始化IP列表
+func Init(ipList []string) {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ // 先清空再初始化
+ ipMap = make(map[string]struct{}, 32)
+ for _, item := range ipList {
+ ipMap[item] = struct{}{}
+ }
+}
+
+// 初始化ip字符串(以分隔符分割的,分隔符为:",", ";", ":", "|", "||")
+func InitString(ipStr string) {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ // 先清空再初始化
+ ipMap = make(map[string]struct{}, 32)
+ for _, item := range stringUtil.Split(ipStr, nil) {
+ ipMap[item] = struct{}{}
+ }
+}
+
+func AddString(ipStr string) {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ // 先清空再初始化
+ if ipMap == nil {
+ ipMap = make(map[string]struct{}, 32)
+ }
+
+ for _, item := range stringUtil.Split(ipStr, nil) {
+ ipMap[item] = struct{}{}
+ }
+}
+
+// RegisterIpCheckFunc 注册Ip检查函数
+func RegisterIpCheckFunc(funcName string, funcItem func(string) bool) {
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ ipCheckFuncList = append(ipCheckFuncList, funcItem)
+}
+
+func isLocalValid(ip string) bool {
+ mutex.RLock()
+ defer mutex.RUnlock()
+
+ _, exist := ipMap[ip]
+ return exist
+}
+
+func isCheckFuncValid(ip string) bool {
+ mutex.RLock()
+ defer mutex.RUnlock()
+
+ for _, funcItem := range ipCheckFuncList {
+ if funcItem(ip) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// 判断传入的Ip是否有效
+// ip:ip
+// 返回值:
+// 是否有效
+func IsIpValid(ip string) bool {
+ return isLocalValid(ip) || isCheckFuncValid(ip)
+}
diff --git a/.svn/pristine/18/18086fba2a253139cdd05cf26644b4f525c60e99.svn-base b/.svn/pristine/18/18086fba2a253139cdd05cf26644b4f525c60e99.svn-base
new file mode 100644
index 0000000..444c3b4
--- /dev/null
+++ b/.svn/pristine/18/18086fba2a253139cdd05cf26644b4f525c60e99.svn-base
@@ -0,0 +1,210 @@
+package managecenterModel
+
+import (
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "goutil/stringUtil"
+ "goutil/typeUtil"
+)
+
+// 游戏版本
+type ResourceVersion struct {
+ // 资源版本唯一标识
+ Id int32 `json:"ResourceVersionID"`
+
+ // 资源版本名称
+ Name string `json:"ResourceVersionName"`
+
+ // 资源版本的url地址
+ Url string `json:"ResourceVersionUrl"`
+
+ // 资源大小
+ Size int32 `json:"Size"`
+
+ // 资源文件MD5加密的结果
+ MD5 string `json:"MD5"`
+
+ //大区Id
+ AreaID int32 `json:"AreaID"`
+
+ // 资源生效时间
+ StartTime string `json:"StartTime"`
+ StartTimeTick int64 `json:"StartTimeTick"`
+
+ // 资源失效时间
+ EndTime string `json:"EndTime"`
+ EndTimeTick int64 `json:"EndTimeTick"`
+
+ // 添加时间
+ Crdate string `json:"Crdate"`
+ CrdateTick int64 `json:"CrdateTick"`
+
+ // 更新时间
+ UpdateTime string `json:"UpdateTime"`
+ UpdateTimeTick int64 `json:"UpdateTimeTick"`
+
+ // 是否重启客户端
+ IfRestart int32 `json:"IfRestart"`
+
+ // 是否禁用
+ IfDelete int32 `json:"IfDelete"`
+
+ // 是否审核服下载
+ IfAuditServiceDownload int32 `json:"IfAuditServiceDownload"`
+
+ // 资源所属的合作商ID集合
+ PartnerIds string `json:"PartnerIDs"`
+
+ // 资源所属的游戏版本ID集合
+ GameVersionIds string `json:"GameVersionIDs"`
+}
+
+// 判断资源是否包含指定合作商
+// partnerId:合作商Id
+// 返回值
+// 是否包含
+func (this *ResourceVersion) ContainsPartner(partnerId int32) bool {
+ partnerIdList, _ := stringUtil.SplitToInt32Slice(this.PartnerIds, ",")
+ for _, item := range partnerIdList {
+ if item == partnerId {
+ return true
+ }
+ }
+
+ return false
+}
+
+// 判断资源是否包含指定游戏版本
+// gameVersionId:游戏版本Id
+// 返回值
+// 是否包含
+func (this *ResourceVersion) ContainsGameVersion(gameVersionId int32) bool {
+ gameVersionIdList, _ := stringUtil.SplitToInt32Slice(this.GameVersionIds, ",")
+ for _, item := range gameVersionIdList {
+ if item == gameVersionId {
+ return true
+ }
+ }
+
+ return false
+}
+
+// 获取有效资源包
+func GetAvailableResource(resourceVersionList []*ResourceVersion, partnerId, gameVersionId int32, resourceVersionName string, offTest OfficialOrTest) (availableResourceVersion map[string]interface{}) {
+
+ if len(resourceVersionList) == 0 {
+ return
+ }
+
+ //判断资源是否有效
+ _, hashCode, isVaild := IsResourceVersionNameValid(resourceVersionName)
+ if !isVaild {
+ return
+ }
+
+ //根据合作商Id和游戏版本Id和开始时间来过滤
+ var targetResourceVersionList []*ResourceVersion
+ for _, resourceVersion := range resourceVersionList {
+ startime, err := typeUtil.DateTime(resourceVersion.StartTimeTick)
+ if resourceVersion.ContainsPartner(partnerId) && resourceVersion.ContainsGameVersion(gameVersionId) && err == nil && startime.Before(time.Now()) {
+ targetResourceVersionList = append(targetResourceVersionList, resourceVersion)
+ }
+ }
+
+ if len(targetResourceVersionList) == 0 {
+ return
+ }
+
+ //组装数据
+
+ //按照资源Id进行降序排列
+ sort.Slice(targetResourceVersionList, func(i, j int) bool {
+ return targetResourceVersionList[i].SortByIdDesc(targetResourceVersionList[j])
+ })
+
+ //取出资源号最大的资源,如果与传入的资源名称相等,则表示没有新资源
+ availableResourceVersion = make(map[string]interface{}, 0)
+ newResource := targetResourceVersionList[0]
+ availableResourceVersion["ResourceVersionName"] = newResource.Name
+ availableResourceVersion["Url"] = strings.Replace(newResource.Url, ".zip", "", -1)
+
+ if newResource.Name == resourceVersionName {
+
+ //是否有新资源,如果为fasle,也需要返回project.manifest.temp.zip 用于子包验证
+ availableResourceVersion["IsNewResource"] = false
+
+ return
+ }
+
+ //判断资源号中的HashCode是否相等,如果相等,则表示没有新资源;如果传入的timeTick>最新的timeTick说明服务器没有被刷新,表示没有新资源
+ _, newHashCode, newIsVaild := IsResourceVersionNameValid(newResource.Name)
+ if !newIsVaild {
+ return
+ }
+
+ if compareRes := strings.Compare(hashCode, newHashCode); compareRes == 0 {
+ //是否有新资源,如果为fasle,也需要返回project.manifest.temp.zip 用于子包验证
+ availableResourceVersion["IsNewResource"] = false
+
+ return
+ }
+
+ if offTest == Con_Test && newResource.IfAuditServiceDownload == 0 {
+ return nil
+ }
+
+ availableResourceVersion["IsNewResource"] = true
+
+ return
+}
+
+// 按照Id进行升序排序
+// target:另一个资源对象
+// 是否是小于
+func (this *ResourceVersion) SortByIdAsc(target *ResourceVersion) bool {
+ return this.Id < target.Id
+}
+
+// 按照Id进行降序排序
+// target:另一个资源对象
+// 是否是大于
+func (this *ResourceVersion) SortByIdDesc(target *ResourceVersion) bool {
+ return this.Id > target.Id
+}
+
+//判断资源版本是否有效
+func IsResourceVersionNameValid(resourceVersionName string) (timeTick int64, hashCode string, isValid bool) {
+ if len(resourceVersionName) == 0 {
+ isValid = false
+
+ return
+ }
+
+ if index := strings.Index(resourceVersionName, "_"); index == -1 {
+ resourceVersionName = fmt.Sprintf("0_%s", resourceVersionName)
+ }
+
+ resourceList := stringUtil.Split(resourceVersionName, []string{"_"})
+ if len(resourceList) != 2 {
+ isValid = false
+
+ return
+ }
+
+ //解析timeTick
+ timeTick, err := strconv.ParseInt(resourceList[0], 10, 64)
+ if err != nil {
+ isValid = false
+
+ return
+ }
+
+ hashCode = resourceList[1]
+ isValid = true
+
+ return
+}
diff --git a/.svn/pristine/18/1838ff95fb3a29c19e78e2e5e1e308e4bc2551c4.svn-base b/.svn/pristine/18/1838ff95fb3a29c19e78e2e5e1e308e4bc2551c4.svn-base
new file mode 100644
index 0000000..1e2afb3
--- /dev/null
+++ b/.svn/pristine/18/1838ff95fb3a29c19e78e2e5e1e308e4bc2551c4.svn-base
@@ -0,0 +1,73 @@
+package redisUtil
+
+import (
+ "github.com/gomodule/redigo/redis"
+)
+
+func (this *RedisPool) Int(reply interface{}) (int, error) {
+ return redis.Int(reply, nil)
+}
+
+func (this *RedisPool) Int64(reply interface{}) (int64, error) {
+ return redis.Int64(reply, nil)
+}
+
+func (this *RedisPool) Uint64(reply interface{}) (uint64, error) {
+ return redis.Uint64(reply, nil)
+}
+
+func (this *RedisPool) Float64(reply interface{}) (float64, error) {
+ return redis.Float64(reply, nil)
+}
+
+func (this *RedisPool) String(reply interface{}) (string, error) {
+ return redis.String(reply, nil)
+}
+
+func (this *RedisPool) Bytes(reply interface{}) ([]byte, error) {
+ return redis.Bytes(reply, nil)
+}
+
+func (this *RedisPool) Bool(reply interface{}) (bool, error) {
+ return redis.Bool(reply, nil)
+}
+
+func (this *RedisPool) Values(reply interface{}) ([]interface{}, error) {
+ return redis.Values(reply, nil)
+}
+
+func (this *RedisPool) Ints(reply interface{}) ([]int, error) {
+ return redis.Ints(reply, nil)
+}
+
+func (this *RedisPool) Int64s(reply interface{}) ([]int64, error) {
+ return redis.Int64s(reply, nil)
+}
+
+func (this *RedisPool) Float64s(reply interface{}) ([]float64, error) {
+ return redis.Float64s(reply, nil)
+}
+
+func (this *RedisPool) Strings(reply interface{}) ([]string, error) {
+ return redis.Strings(reply, nil)
+}
+
+func (this *RedisPool) ByteSlices(reply interface{}) ([][]byte, error) {
+ return redis.ByteSlices(reply, nil)
+}
+
+func (this *RedisPool) IntMap(reply interface{}) (map[string]int, error) {
+ return redis.IntMap(reply, nil)
+}
+
+func (this *RedisPool) Int64Map(reply interface{}) (map[string]int64, error) {
+ return redis.Int64Map(reply, nil)
+}
+
+func (this *RedisPool) StringMap(reply interface{}) (map[string]string, error) {
+ return redis.StringMap(reply, nil)
+}
+
+func (this *RedisPool) Positions(reply interface{}) ([]*[2]float64, error) {
+ return redis.Positions(reply, nil)
+}
diff --git a/.svn/pristine/18/1849d81e98b05475fc80c58a3255322d410a1a84.svn-base b/.svn/pristine/18/1849d81e98b05475fc80c58a3255322d410a1a84.svn-base
new file mode 100644
index 0000000..4e5137f
--- /dev/null
+++ b/.svn/pristine/18/1849d81e98b05475fc80c58a3255322d410a1a84.svn-base
@@ -0,0 +1,68 @@
+package intAndBytesUtil
+
+import (
+ "encoding/binary"
+ "testing"
+)
+
+func TestInt16ToBytes(t *testing.T) {
+ var expectedBigEndian []byte = []byte{1, 0}
+ var expectedLittleEndian []byte = []byte{0, 1}
+ var givenInt int16 = 256
+
+ result := Int16ToBytes(givenInt, binary.BigEndian)
+ if equal(result, expectedBigEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedBigEndian)
+ }
+
+ result = Int16ToBytes(givenInt, binary.LittleEndian)
+ if equal(result, expectedLittleEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedLittleEndian)
+ }
+}
+
+func TestInt32ToBytes(t *testing.T) {
+ var expectedBigEndian []byte = []byte{0, 0, 1, 0}
+ var expectedLittleEndian []byte = []byte{0, 1, 0, 0}
+ var givenInt int32 = 256
+
+ result := Int32ToBytes(givenInt, binary.BigEndian)
+ if equal(result, expectedBigEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedBigEndian)
+ }
+
+ result = Int32ToBytes(givenInt, binary.LittleEndian)
+ if equal(result, expectedLittleEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedLittleEndian)
+ }
+}
+
+func TestInt64ToBytes(t *testing.T) {
+ var expectedBigEndian []byte = []byte{0, 0, 0, 0, 0, 0, 1, 0}
+ var expectedLittleEndian []byte = []byte{0, 1, 0, 0, 0, 0, 0, 0}
+ var givenInt int64 = 256
+
+ result := Int64ToBytes(givenInt, binary.BigEndian)
+ if equal(result, expectedBigEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedBigEndian)
+ }
+
+ result = Int64ToBytes(givenInt, binary.LittleEndian)
+ if equal(result, expectedLittleEndian) == false {
+ t.Errorf("IntToBytes(%v) failed.Got %v, expected %v", givenInt, result, expectedLittleEndian)
+ }
+}
+
+func equal(b1, b2 []byte) bool {
+ if len(b1) != len(b2) {
+ return false
+ }
+
+ for i := 0; i < len(b1); i++ {
+ if b1[i] != b2[i] {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/.svn/pristine/18/18e8f4fcc246b38d375d7d7cf3d46f677afc9de1.svn-base b/.svn/pristine/18/18e8f4fcc246b38d375d7d7cf3d46f677afc9de1.svn-base
new file mode 100644
index 0000000..1a1566e
--- /dev/null
+++ b/.svn/pristine/18/18e8f4fcc246b38d375d7d7cf3d46f677afc9de1.svn-base
@@ -0,0 +1,2 @@
+Log/*
+logs/*
\ No newline at end of file
diff --git a/.svn/pristine/19/19cd06f67349e079d14ba9d6e284cd8a2cbd2ca4.svn-base b/.svn/pristine/19/19cd06f67349e079d14ba9d6e284cd8a2cbd2ca4.svn-base
new file mode 100644
index 0000000..0139d3d
--- /dev/null
+++ b/.svn/pristine/19/19cd06f67349e079d14ba9d6e284cd8a2cbd2ca4.svn-base
@@ -0,0 +1,1501 @@
+package redisUtil
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/gomodule/redigo/redis"
+)
+
+var (
+ redisPoolObj_hash *RedisPool
+)
+
+func init() {
+ redisPoolObj_hash = NewRedisPool("testPool", "10.1.0.21:6379", "redis_pwd", 5, 500, 200, 10*time.Second, 5*time.Second)
+}
+
+func TestHSet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 设置一个新域:
+
+ redis> HSET website google "www.g.cn"
+ (integer) 1
+ */
+ key := "website"
+ field := "google"
+ value := "www.g.cn"
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HGET website google
+ "www.g.cn"
+ */
+ expected2 := "www.g.cn"
+ got2, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s and field:%s should exist, but now it doesn't", key, field)
+ return
+ }
+ got2_str, err := redis.String(got2, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got2_str != expected2 {
+ t.Errorf("Expected to get %s, but got %s", expected2, got2_str)
+ return
+ }
+
+ /*
+ 对一个已存在的域进行更新:
+ redis> HSET website google "www.google.com"
+ (integer) 0
+
+ */
+ field = "google"
+ value = "www.google.com"
+ expected = 0
+ got, err = redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HGET website google
+ "www.google.com"
+ */
+ expected3 := "www.google.com"
+ got3, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s and field:%s should exist, but now it doesn't", key, field)
+ return
+ }
+ got3_str, err := redis.String(got3, nil)
+ if err != nil {
+ t.Fail()
+ }
+ if got3_str != expected3 {
+ t.Errorf("Expected to get %s, but got %s", expected3, got3_str)
+ return
+ }
+
+ /*
+ 对一个已存在的域进行更新:
+ redis> HSET website google 1
+ (integer) 0
+
+ */
+ field = "google"
+ value4 := 1
+ expected = 0
+ got, err = redisPoolObj_hash.HSet(key, field, value4)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HGET website google
+ "www.google.com"
+ */
+ expected4 := 1
+ got4, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s and field:%s should exist, but now it doesn't", key, field)
+ return
+ }
+ got4_int, err := redis.Int(got4, nil)
+ if err != nil {
+ t.Fail()
+ }
+ if got4_int != expected4 {
+ t.Errorf("Expected to get %d, but got %d", expected4, got4_int)
+ return
+ }
+}
+
+func TestHSetNX(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 域尚未存在, 设置成功:
+
+ redis> HSETNX database key-value-store Redis
+ (integer) 1
+ */
+ key := "database"
+ field := "key-value-store"
+ value := "Redis"
+ successful, err := redisPoolObj_hash.HSetNX(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("HSetNX key:%s, field:%s should be successful, but now it's not.", key, field)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HGET database key-value-store
+ "Redis"
+ */
+ expected := "Redis"
+ gottmp, exist, err := redisPoolObj_hash.HGet(key, field)
+ got, err := redis.String(gottmp, err)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("Key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but got %s", expected, got)
+ return
+ }
+
+ /*
+ 域已经存在, 设置未成功, 域原有的值未被改变:
+
+ redis> HSETNX database key-value-store Riak
+ (integer) 0
+ */
+ value = "Riak"
+ successful, err = redisPoolObj_hash.HSetNX(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if successful {
+ t.Errorf("HSetNX key:%s, field:%s should be not successful, but now it is.", key, field)
+ return
+ }
+
+ /*
+ redis> HGET database key-value-store
+ "Redis"
+ */
+ expected = "Redis"
+ gottmp, exist, err = redisPoolObj_hash.HGet(key, field)
+ got, err = redis.String(gottmp, err)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("Key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but got %s", expected, got)
+ return
+ }
+}
+
+func TestHGet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 域存在的情况:
+
+ redis> HSET homepage redis redis.com
+ (integer) 1
+ */
+ key := "homepage"
+ field := "redis"
+ value := "redis.com"
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HGET homepage redis
+ "redis.com"
+ */
+ expected2 := "redis.com"
+ got2, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s and field:%s should exist, but now it doesn't", key, field)
+ return
+ }
+ got2_str, err := redis.String(got2, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got2_str != expected2 {
+ t.Errorf("Expected to get %s, but got %s", expected2, got2_str)
+ return
+ }
+
+ /*
+ 域不存在的情况:
+
+ redis> HGET site mysql
+ (nil)
+ */
+ key = "site"
+ field = "mysql"
+ _, exist, err = redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s and field:%s should not exist, but now it does", key, field)
+ return
+ }
+}
+
+func TestHExists(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 给定域不存在:
+
+ redis> HEXISTS phone myphone
+ (integer) 0
+ 给定域存在:
+ */
+ key := "phone"
+ field := "myphone"
+ expected := false
+ got, err := redisPoolObj_hash.HExists(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ /*
+ redis> HSET phone myphone nokia-1110
+ (integer) 1
+ */
+ value := "nokia-1110"
+ expected2 := 1
+ got2, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HEXISTS phone myphone
+ (integer) 1
+ */
+ expected3 := true
+ got3, err := redisPoolObj_hash.HExists(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %t, but now got %t", expected3, got3)
+ return
+ }
+}
+
+func TestHDel(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 测试数据
+ */
+ key := "abbr"
+ redisPoolObj_hash.HSet(key, "a", "apple")
+ redisPoolObj_hash.HSet(key, "b", "banana")
+ redisPoolObj_hash.HSet(key, "c", "cat")
+ redisPoolObj_hash.HSet(key, "d", "dog")
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 删除单个域
+
+ redis> HDEL abbr a
+ (integer) 1
+ */
+ field := "a"
+ expected := 1
+ got, err := redisPoolObj_hash.HDel(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ # 删除不存在的域
+
+ redis> HDEL abbr not-exists-field
+ (integer) 0
+ */
+ field = "not-exists-field"
+ expected = 0
+ got, err = redisPoolObj_hash.HDel(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ # 删除多个域
+
+ redis> HDEL abbr b c
+ (integer) 2
+ */
+ fields := []string{"b", "c"}
+ expected = 2
+ got, err = redisPoolObj_hash.HDel(key, fields...)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HGETALL abbr
+ 1) "d"
+ 2) "dog"
+ */
+}
+
+func TestHLen(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> HSET db redis redis.com
+ (integer) 1
+ */
+ key := "db"
+ field := "redis"
+ value := "redis.com"
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HSET db mysql mysql.com
+ (integer) 1
+ */
+ field = "mysql"
+ value = "mysql.com"
+ expected = 1
+ got, err = redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HLEN db
+ (integer) 2
+ */
+ expected = 2
+ got, err = redisPoolObj_hash.HLen(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HSET db mongodb mongodb.org
+ (integer) 1
+ */
+ field = "mongodb"
+ value = "mongodb.org"
+ expected = 1
+ got, err = redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HLEN db
+ (integer) 3
+ */
+ expected = 3
+ got, err = redisPoolObj_hash.HLen(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+}
+
+func TestHStrlen(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> HMSET myhash f1 "HelloWorld" f2 "99" f3 "-256"
+ OK
+ */
+ key := "myhash"
+ redisPoolObj_hash.HSet(key, "f1", "HelloWorld")
+ redisPoolObj_hash.HSet(key, "f2", "99")
+ redisPoolObj_hash.HSet(key, "f3", "-256")
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HSTRLEN myhash f1
+ (integer) 10
+ */
+ expected := 10
+ field := "f1"
+ got, err := redisPoolObj_hash.HStrlen(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HSTRLEN myhash f2
+ (integer) 2
+ */
+ expected = 2
+ field = "f2"
+ got, err = redisPoolObj_hash.HStrlen(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HSTRLEN myhash f3
+ (integer) 4
+ */
+ expected = 4
+ field = "f3"
+ got, err = redisPoolObj_hash.HStrlen(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+}
+
+func TestHIncrBy(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # increment 为正数
+
+ redis> HEXISTS counter page_view # 对空域进行设置
+ (integer) 0
+ */
+ key := "counter"
+ field := "page_view"
+ exist, err := redisPoolObj_hash.HExists(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s, field:%s should not exist, but now it does.", key, field)
+ return
+ }
+
+ /*
+ redis> HINCRBY counter page_view 200
+ (integer) 200
+ */
+ increment := int64(200)
+ expected := int64(200)
+ got, err := redisPoolObj_hash.HIncrBy(key, field, increment)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HGET counter page_view
+ "200"
+ */
+ expected = 200
+ got2, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ got2_int64, err := redis.Int64(got2, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got2_int64 != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got2_int64)
+ return
+ }
+
+ /*
+ # increment 为负数
+
+ redis> HGET counter page_view
+ "200"
+ */
+ /*
+ redis> HINCRBY counter page_view -50
+ (integer) 150
+ */
+ increment = -50
+ expected = 150
+ got, err = redisPoolObj_hash.HIncrBy(key, field, increment)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HGET counter page_view
+ "150"
+ */
+ expected = 150
+ got3, exist, err := redisPoolObj_hash.HGet(key, field)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ got3_int64, err := redis.Int64(got3, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got3_int64 != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got3_int64)
+ return
+ }
+
+ /*
+ # 尝试对字符串值的域执行HINCRBY命令
+
+ redis> HSET myhash string hello,world # 设定一个字符串值
+ (integer) 1
+ */
+ key2 := "myhash"
+ field2 := "string"
+ value2 := "hello,world"
+ expected4 := 1
+ got4, err := redisPoolObj_hash.HSet(key2, field2, value2)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected to get %d, but now got %d", expected4, got4)
+ return
+ }
+ deleteKeys = append(deleteKeys, key2)
+
+ /*
+ redis> HGET myhash string
+ "hello,world"
+ */
+ expected5 := "hello,world"
+ got5_interface, exist, err := redisPoolObj_hash.HGet(key2, field2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ got5, err := redis.String(got5_interface, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got5 != expected5 {
+ t.Errorf("Expected to get %s, but now got %s", expected5, got5)
+ return
+ }
+
+ /*
+ redis> HINCRBY myhash string 1 # 命令执行失败,错误。
+ (error) ERR hash value is not an integer
+ */
+ increment = 1
+ got, err = redisPoolObj_hash.HIncrBy(key2, field2, increment)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ /*
+ redis> HGET myhash string # 原值不变
+ "hello,world"
+ */
+ expected6 := "hello,world"
+ got6_interface, exist, err := redisPoolObj_hash.HGet(key2, field2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field)
+ return
+ }
+ got6, err := redis.String(got6_interface, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got6 != expected6 {
+ t.Errorf("Expected to get %s, but now got %s", expected6, got6)
+ return
+ }
+}
+
+func TestHIncrByFloat(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 值和增量都是普通小数
+
+ redis> HSET mykey field 10.50
+ (integer) 1
+ redis> HINCRBYFLOAT mykey field 0.1
+ "10.6"
+ */
+ key := "mykey"
+ field := "field"
+ value := 10.50
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ increment := 0.1
+ expected2 := 10.6
+ got2, err := redisPoolObj_hash.HIncrByFloat(key, field, increment)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %f, but now got %f", expected2, got2)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 值和增量都是指数符号
+
+ redis> HSET mykey field 5.0e3
+ (integer) 0
+ redis> HINCRBYFLOAT mykey field 2.0e2
+ "5200"
+ */
+ value3 := 5.0e3
+ expected3 := 0
+ got3, err := redisPoolObj_hash.HSet(key, field, value3)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d", expected3, got3)
+ return
+ }
+
+ increment4 := 2.0e2
+ expected4 := 5200.0
+ got4, err := redisPoolObj_hash.HIncrByFloat(key, field, increment4)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected to get %f, but now got %f", expected4, got4)
+ return
+ }
+
+ /*
+ # 对不存在的键执行 HINCRBYFLOAT
+
+ redis> EXISTS price
+ (integer) 0
+ redis> HINCRBYFLOAT price milk 3.5
+ "3.5"
+ redis> HGETALL price
+ 1) "milk"
+ 2) "3.5"
+ */
+ key5 := "price"
+ exist5, err := redisPoolObj_hash.Exists(key5)
+ if err != nil {
+ t.Fail()
+ }
+ if exist5 {
+ t.Errorf("The key:%s should not exist, but now it does.", key5)
+ return
+ }
+
+ field5 := "milk"
+ increment5 := 3.5
+ expected5 := 3.5
+ got5, err := redisPoolObj_hash.HIncrByFloat(key5, field5, increment5)
+ if err != nil {
+ t.Fail()
+ }
+ if got5 != expected5 {
+ t.Errorf("Expected to get %f, but now got %f", expected5, got5)
+ return
+ }
+
+ got5_interface, exist, err := redisPoolObj_hash.HGet(key5, field5)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't", key5, field5)
+ return
+ }
+ got5, err = redis.Float64(got5_interface, err)
+ if err != nil {
+ t.Fail()
+ }
+ if got5 != expected5 {
+ t.Errorf("Expected to get %f, but now got %f", expected5, got5)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key5)
+
+ /*
+ # 对不存在的域进行 HINCRBYFLOAT
+
+ redis> HGETALL price
+ 1) "milk"
+ 2) "3.5"
+ redis> HINCRBYFLOAT price coffee 4.5 # 新增 coffee 域
+ "4.5"
+ redis> HGETALL price
+ 1) "milk"
+ 2) "3.5"
+ 3) "coffee"
+ 4) "4.5"
+ */
+ key6 := "price"
+ field6 := "coffee"
+ increment6 := 4.5
+ expected6 := 4.5
+ got6, err := redisPoolObj_hash.HIncrByFloat(key6, field6, increment6)
+ if err != nil {
+ t.Fail()
+ }
+ if got6 != expected6 {
+ t.Errorf("Expected to get %f, but now got %f", expected6, got6)
+ return
+ }
+
+ got6_interface, exist, err := redisPoolObj_hash.HGet(key6, field6)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't", key6, field6)
+ return
+ }
+ got6, err = redis.Float64(got6_interface, err)
+ if got6 != expected6 {
+ t.Errorf("Expected to get %f, but now got %f", expected6, got6)
+ return
+ }
+}
+
+func TestHMSet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ // HMSet
+ key := "people"
+ people := &People{
+ Jack: "Jack Ma",
+ Gump: "Gump Li",
+ }
+ err := redisPoolObj_hash.HMSet(key, people)
+ if err != nil {
+ t.Fail()
+ }
+
+ data := make(map[string]interface{})
+ data["Jordan"] = "Jordan Zuo"
+ err = redisPoolObj_hash.HMSet(key, data)
+ if err != nil {
+ t.Fail()
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ // HGet
+ field1 := "Jack"
+ expected1 := "Jack Ma"
+ got1_interface, exist1, err := redisPoolObj_hash.HGet(key, field1)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist1 {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field1)
+ return
+ }
+ got1, err := redis.String(got1_interface, nil)
+ if err != nil {
+ t.Fail()
+ }
+ if got1 != expected1 {
+ t.Errorf("Expected to get %s, but now got %s", expected1, got1)
+ return
+ }
+
+ // HGet
+ field2 := "Gump"
+ expected2 := "Gump Li"
+ got2_interface, exist2, err := redisPoolObj_hash.HGet(key, field2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist2 {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field2)
+ return
+ }
+ got2, err := redis.String(got2_interface, nil)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %s, but now got %s", expected2, got2)
+ return
+ }
+
+ field3 := "Jordan"
+ expected3 := "Jordan Zuo"
+ got3_interface, exist3, err := redisPoolObj_hash.HGet(key, field3)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist3 {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field3)
+ return
+ }
+ got3, err := redis.String(got3_interface, nil)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %s, but now got %s", expected3, got3)
+ return
+ }
+}
+
+func TestHMGet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> HMSET pet dog "doudou" cat "nounou" # 一次设置多个域
+ OK
+ */
+ key := "pet"
+ field_value_map := make(map[string]interface{})
+ field_value_map["dog"] = "doudou"
+ field_value_map["cat"] = "nounou"
+ err := redisPoolObj_hash.HMSet(key, field_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HMGET pet dog cat fake_pet # 返回值的顺序和传入参数的顺序一样
+ 1) "doudou"
+ 2) "nounou"
+ 3) (nil) # 不存在的域返回nil值
+ */
+ expected := []string{"doudou", "nounou", ""}
+ reply, exist, err := redisPoolObj_hash.HMGet(key, "dog", "cat", "fake_pet")
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should have items, but now it doesn't.", key)
+ return
+ }
+ got, err := redisPoolObj_hash.Strings(reply)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ }
+}
+
+func TestHKeys(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 哈希表非空
+
+ redis> HMSET website google www.google.com yahoo www.yahoo.com
+ OK
+ */
+ key := "website"
+ field_value_map := make(map[string]interface{})
+ field_value_map["google"] = "www.google.com"
+ field_value_map["yahoo"] = "www.yahoo.com"
+ err := redisPoolObj_hash.HMSet(key, field_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HKEYS website
+ 1) "google"
+ 2) "yahoo"
+ */
+ expected := make([]string, 0, len(field_value_map))
+ for k := range field_value_map {
+ expected = append(expected, k)
+ }
+ got, err := redisPoolObj_hash.HKeys(key)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ }
+
+ /*
+ # 空哈希表/key不存在
+
+ redis> EXISTS fake_key
+ (integer) 0
+ */
+ key2 := "fake_key"
+ exist, err := redisPoolObj_hash.Exists(key2)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key2)
+ return
+ }
+
+ /*
+ redis> HKEYS fake_key
+ (empty list or set)*
+ */
+ expected2 := make([]string, 0, len(field_value_map))
+ got2, err := redisPoolObj_hash.HKeys(key2)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(got2, expected2) == false {
+ t.Errorf("Expected to get %v, but got %v", expected2, got2)
+ }
+}
+
+func TestHVals(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 哈希表非空
+
+ redis> HMSET website google www.google.com yahoo www.yahoo.com
+ OK
+ */
+ key := "website"
+ field_value_map := make(map[string]interface{})
+ field_value_map["google"] = "www.google.com"
+ field_value_map["yahoo"] = "www.yahoo.com"
+ err := redisPoolObj_hash.HMSet(key, field_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HVALS website
+ 1) "www.google.com"
+ 2) "www.yahoo.com"
+ */
+ expected := make([]string, 0, len(field_value_map))
+ for _, v := range field_value_map {
+ if v_str, ok := v.(string); ok {
+ expected = append(expected, v_str)
+ }
+ }
+ reply, err := redisPoolObj_hash.HVals(key)
+ if err != nil {
+ t.Fail()
+ }
+ got, err := redisPoolObj_hash.Strings(reply)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ }
+
+ /*
+ # 空哈希表/不存在的key
+
+ redis> EXISTS not_exists
+ (integer) 0
+ */
+ key2 := "fake_key"
+ exist, err := redisPoolObj_hash.Exists(key2)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key2)
+ return
+ }
+
+ /*
+ redis> HVALS not_exists
+ (empty list or set)
+ */
+ expected2 := make([]string, 0, len(field_value_map))
+ for _, v := range field_value_map {
+ if v_str, ok := v.(string); ok {
+ expected2 = append(expected2, v_str)
+ }
+ }
+ reply2, err := redisPoolObj_hash.HVals(key)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_hash.Strings(reply2)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(got2, expected2) == false {
+ t.Errorf("Expected to get %v, but got %v", expected2, got2)
+ }
+}
+
+func TestHGetAll(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> HSET people jack "Jack Sparrow"
+ (integer) 1
+ */
+ key := "people"
+ field1 := "Jack"
+ value1 := "Jack Sparrow"
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field1, value1)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HSET people gump "Forrest Gump"
+ (integer) 1
+ */
+ field2 := "Gump"
+ value2 := "Forrest Gump"
+ expected = 1
+ got, err = redisPoolObj_hash.HSet(key, field2, value2)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HGETALL people
+ 1) "Jack" # 域
+ 2) "Jack Sparrow" # 值
+ 3) "Gump"
+ 4) "Forrest Gump"
+ */
+
+ reply, err := redisPoolObj_hash.HGetAll(key)
+ if err != nil {
+ t.Fail()
+ }
+ field_value_map, err := redisPoolObj_hash.StringMap(reply)
+ if err != nil {
+ t.Fail()
+ }
+
+ expected1 := "Jack Sparrow"
+ got1, exist1 := field_value_map[field1]
+ if !exist1 {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field1)
+ return
+ }
+ if got1 != expected1 {
+ t.Errorf("Expected to get %s, but now got %s", expected1, got1)
+ return
+ }
+
+ expected2 := "Forrest Gump"
+ got2, exist2 := field_value_map[field2]
+ if !exist2 {
+ t.Errorf("The key:%s, field:%s should exist, but now it doesn't.", key, field2)
+ return
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %s, but now got %s", expected2, got2)
+ return
+ }
+}
+
+func TestHGetAll_Struct(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> HSET people jack "Jack Sparrow"
+ (integer) 1
+ */
+ key := "people"
+ field := "Jack"
+ value := "Jack Sparrow"
+ expected := 1
+ got, err := redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> HSET people gump "Forrest Gump"
+ (integer) 1
+ */
+ field = "Gump"
+ value = "Forrest Gump"
+ expected = 1
+ got, err = redisPoolObj_hash.HSet(key, field, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> HGETALL people
+ 1) "Jack" # 域
+ 2) "Jack Sparrow" # 值
+ 3) "Gump"
+ 4) "Forrest Gump"
+ */
+
+ got2 := new(People)
+ expected2 := &People{
+ Jack: "Jack Sparrow",
+ Gump: "Forrest Gump",
+ }
+ exist, err := redisPoolObj_hash.HGetAll_Struct(key, got2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ if got2.TheSame(expected2) == false {
+ t.Errorf("Expected to get:%s, but now got %s", expected2, got2)
+ }
+}
+
+type People struct {
+ Jack string
+ Gump string
+}
+
+func (this *People) TheSame(other *People) bool {
+ return this.Jack == other.Jack && this.Gump == other.Gump
+}
+
+func (this *People) String() string {
+ return fmt.Sprintf("{\"Jack\": %s, \"Gump\":%s}", this.Jack, this.Gump)
+}
diff --git a/.svn/pristine/1a/1a85336be2fbc6102cfdbb3d5e7b672995ea4226.svn-base b/.svn/pristine/1a/1a85336be2fbc6102cfdbb3d5e7b672995ea4226.svn-base
new file mode 100644
index 0000000..e8dd3cd
--- /dev/null
+++ b/.svn/pristine/1a/1a85336be2fbc6102cfdbb3d5e7b672995ea4226.svn-base
@@ -0,0 +1,114 @@
+package redisUtil
+
+import (
+ "testing"
+ "time"
+)
+
+var (
+ redisPoolObj *RedisPool
+)
+
+func init() {
+ redisPoolObj = NewRedisPool("testPool", "10.1.0.21:6379", "redis_pwd", 5, 500, 200, 10*time.Second, 5*time.Second)
+}
+
+func TestGetName(t *testing.T) {
+ expected := "testPool"
+ got := redisPoolObj.GetName()
+ if expected != got {
+ t.Errorf("Expected to get %s, but got %s", expected, got)
+ return
+ }
+}
+
+func TestGetAddress(t *testing.T) {
+ expected := "10.1.0.21:6379"
+ got := redisPoolObj.GetAddress()
+ if expected != got {
+ t.Errorf("Expected to get %s, but got %s", expected, got)
+ return
+ }
+}
+
+func converInterfaceSliceToStringSlice(sourceList []interface{}) []string {
+ targetList := make([]string, 0, len(sourceList))
+ for _, item := range sourceList {
+ if item == nil {
+ targetList = append(targetList, "")
+ } else if item_str, ok := item.(string); ok {
+ targetList = append(targetList, item_str)
+ } else if item_bytes, ok2 := item.([]byte); ok2 {
+ targetList = append(targetList, string(item_bytes))
+ }
+ }
+
+ return targetList
+}
+
+func isTwoOrderedSliceEqual(list1, list2 []string) bool {
+ if list1 == nil && list2 == nil {
+ return true
+ }
+
+ if list1 == nil || list2 == nil {
+ return false
+ }
+
+ if len(list1) != len(list2) {
+ return false
+ }
+
+ for i := 0; i < len(list1); i++ {
+ if list1[i] != list2[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+func isTwoUnorderedSliceEqual(list1, list2 []string) bool {
+ if list1 == nil && list2 == nil {
+ return true
+ }
+
+ if list1 == nil || list2 == nil {
+ return false
+ }
+
+ if len(list1) != len(list2) {
+ return false
+ }
+
+ map1 := make(map[string]struct{})
+ map2 := make(map[string]struct{})
+
+ for _, item := range list1 {
+ map1[item] = struct{}{}
+ }
+ for _, item := range list2 {
+ map2[item] = struct{}{}
+ }
+
+ for k := range map1 {
+ if _, exist := map2[k]; !exist {
+ return false
+ }
+ }
+
+ return true
+}
+
+func getDistinctKeyList(keyList []string) []string {
+ distinctKeyList := make([]string, 0, len(keyList))
+ keyMap := make(map[string]struct{})
+ for _, key := range keyList {
+ if _, exist := keyMap[key]; !exist {
+ distinctKeyList = append(distinctKeyList, key)
+ keyMap[key] = struct{}{}
+ }
+ }
+
+ return distinctKeyList
+}
diff --git a/.svn/pristine/1a/1aeca629abfb9fb4344aeefa35ceadca73f1fe4c.svn-base b/.svn/pristine/1a/1aeca629abfb9fb4344aeefa35ceadca73f1fe4c.svn-base
new file mode 100644
index 0000000..bd507a9
--- /dev/null
+++ b/.svn/pristine/1a/1aeca629abfb9fb4344aeefa35ceadca73f1fe4c.svn-base
@@ -0,0 +1,587 @@
+package typeUtil
+
+import (
+ "testing"
+ "time"
+)
+
+func TestMapDataByte(t *testing.T) {
+ TestMapDataUint8(t)
+}
+
+func TestMapDataInt(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected int = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Int(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Int(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Int(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataInt8(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected int8 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Int8(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Int8(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Int8(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataInt16(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected int16 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Int16(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Int16(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Int16(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataInt32(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected int32 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Int32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Int32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Int32(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataInt64(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected int64 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Int64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Int64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Int64(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataUint(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected uint = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Uint(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Uint(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Uint(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataUint8(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected uint8 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Uint8(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Uint8(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Uint8(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataUint16(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected uint16 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Uint16(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Uint16(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Uint16(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataUint32(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected uint32 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Uint32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Uint32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Uint32(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataUint64(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected uint64 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Uint64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Uint64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Uint64(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %d, but got %d", expected, got)
+ return
+ }
+}
+
+func TestMapDataFloat32(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected float32 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Float32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Float32(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Float32(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %f, but got %f", expected, got)
+ return
+ }
+}
+
+func TestMapDataFloat64(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected float64 = 0
+
+ // Test when key doesn't exist
+ got, err := mapData.Float64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Float64(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = 1
+ expected = 1
+ got, err = mapData.Float64(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %f, but got %f", expected, got)
+ return
+ }
+}
+
+func TestMapDataBool(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected bool = true
+
+ // Test when key doesn't exist
+ got, err := mapData.Bool(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = "abc"
+ got, err = mapData.Bool(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = true
+ expected = true
+ got, err = mapData.Bool(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %t, but got %t", expected, got)
+ return
+ }
+}
+
+func TestMapDataString(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected string = ""
+
+ // Test when key doesn't exist
+ got, err := mapData.String(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist, but type doesn't match
+ mapData[key] = 123
+ expected = "123"
+ got, err = mapData.String(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %s, but got %s", expected, got)
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = "hello"
+ expected = "hello"
+ got, err = mapData.String(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %s, but got %s", expected, got)
+ return
+ }
+}
+
+// Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
+func TestMapDataDateTime(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected time.Time = time.Date(2019, time.December, 25, 12, 0, 0, 0, time.UTC)
+
+ // Test when key doesn't exist
+ got, err := mapData.DateTime(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist but value doesn't match
+ mapData[key] = "123"
+ expected = time.Date(2019, time.December, 25, 12, 0, 0, 0, time.UTC)
+ got, err = mapData.DateTime(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = time.Date(2019, time.December, 25, 12, 0, 0, 0, time.UTC)
+ expected = time.Date(2019, time.December, 25, 12, 0, 0, 0, time.UTC)
+ got, err = mapData.DateTime(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected %s, but got %s", expected, got)
+ return
+ }
+}
+
+func TestMapDataInterface(t *testing.T) {
+ data := make(map[string]interface{})
+ mapData := NewMapData(data)
+ key := "key"
+ var expected *Person
+
+ // Test when key doesn't exist
+ got, err := mapData.Interface(key)
+ if err == nil {
+ t.Errorf("There should be an error, but now there isn't.")
+ return
+ }
+
+ // Test when key exist and value matches
+ mapData[key] = NewPerson("Jordan", 34)
+ expected = NewPerson("Jordan", 34)
+ got, err = mapData.Interface(key)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%s", err)
+ return
+ }
+ if gotPersonObj, ok := got.(*Person); !ok {
+ t.Errorf("Expected type *Person")
+ } else if gotPersonObj.SameAs(expected) == false {
+ t.Errorf("Expected %v, but got %v", expected, got)
+ return
+ }
+}
+
+type Person struct {
+ Name string
+ Age int
+}
+
+func (this *Person) SameAs(other *Person) bool {
+ return this.Name == other.Name && this.Age == other.Age
+}
+
+func NewPerson(name string, age int) *Person {
+ return &Person{
+ Name: name,
+ Age: age,
+ }
+}
diff --git a/.svn/pristine/1a/1af88023dbc796a3f5f0281152a47b2d363859d6.svn-base b/.svn/pristine/1a/1af88023dbc796a3f5f0281152a47b2d363859d6.svn-base
new file mode 100644
index 0000000..87c95ad
--- /dev/null
+++ b/.svn/pristine/1a/1af88023dbc796a3f5f0281152a47b2d363859d6.svn-base
@@ -0,0 +1,54 @@
+package bytesSendUtil
+
+import (
+ "fmt"
+)
+
+/*
+实现sender接口
+*/
+
+type baseSender struct {
+ // 待发送的数据channel
+ waitingDataChan chan dataItem
+
+ // 失败数据缓存
+ cachedDataChan chan dataItem
+
+ // 用于停止协程
+ done chan struct{}
+}
+
+func newBaseSender() *baseSender {
+ return &baseSender{
+ waitingDataChan: make(chan dataItem, 1024),
+ cachedDataChan: make(chan dataItem, 1024000),
+ done: make(chan struct{}),
+ }
+}
+
+// Sender接口
+// Send:
+func (this *baseSender) Send() error {
+ // baseSender不实现发送
+ // 由tcpSender和httpSender实现发送
+ return fmt.Errorf("baseSender dose not have Send Method")
+}
+
+// Sender接口
+// Data: 返回待发送的数据channel
+func (this *baseSender) Data() <-chan dataItem {
+ return this.waitingDataChan
+}
+
+// Sender接口
+// Cache:返回失败数据缓存channel
+func (this *baseSender) Cache() chan dataItem {
+ return this.cachedDataChan
+}
+
+// Sender接口
+// Done:返回channel用于判断是否关闭
+func (this *baseSender) Done() <-chan struct{} {
+ return this.done
+}
diff --git a/.svn/pristine/1b/1b2c410b7678eef959ff8f8c0e69d4051e45ed17.svn-base b/.svn/pristine/1b/1b2c410b7678eef959ff8f8c0e69d4051e45ed17.svn-base
new file mode 100644
index 0000000..616ce39
--- /dev/null
+++ b/.svn/pristine/1b/1b2c410b7678eef959ff8f8c0e69d4051e45ed17.svn-base
@@ -0,0 +1,83 @@
+package notify_util
+
+import (
+ "fmt"
+
+ "goutil/syncUtil"
+)
+
+var (
+ // key:初始化成功的标志名称 val:占位符
+ registerNC = make(map[string]*notifyCenter)
+ mutex = syncUtil.NewRWLocker()
+)
+
+// getItemOrAdd
+// @description: 获取注册的通知对象
+// parameter:
+// @chanGroup:
+// return:
+// @*notifyCenter:
+func getItemOrAdd(chanGroup string) *notifyCenter {
+ if isOk, prevStack, currStack := mutex.Lock(deathLockTime); isOk == false {
+ //记日志
+ errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s \n当前堆栈:\n%s", prevStack, currStack)
+ panic(errMsg)
+ }
+ defer mutex.Unlock()
+
+ nc, exists := registerNC[chanGroup]
+ if exists {
+ return nc
+ }
+
+ nc = newNotifyCenter()
+ registerNC[chanGroup] = nc
+
+ return nc
+}
+
+// Register
+// @description: 注册需要被通知的对象
+// parameter:
+// @chanGroup:通知的分组标识
+// @chanName:唯一标识
+// @cf:回调方法
+// return:
+func Register(chanGroup string, chanName string, cf func()) {
+ nc := getItemOrAdd(chanGroup)
+ nc.register(chanName, cf)
+}
+
+// Unregister
+// @description: 取消启动成功通知注册
+// parameter:
+// @chanGroup:分组标识
+// @name:唯一标识
+// return:
+func Unregister(chanGroup string, name string) {
+ nc := getItemOrAdd(chanGroup)
+ nc.unregister(name)
+}
+
+// Notify
+// @description: 通知分组所有已注册的对象
+// parameter:
+// @chanGroup:分组标识
+// return:
+func Notify(chanGroup string) {
+ nc := getItemOrAdd(chanGroup)
+ nc.notify()
+}
+
+// Notify2
+// @description: 通知所有已注册的对象,该方法会在捕获第一个err的时候停止后续的通知。多用于系统启动的判定
+// parameter:
+// @chanGroup:分组标识
+// return:
+// @err:
+func Notify2(chanGroup string) (err error) {
+ nc := getItemOrAdd(chanGroup)
+ err = nc.notify2()
+ return
+}
diff --git a/.svn/pristine/1b/1b511d8dc10711a9b500c6dea251529f59d249f0.svn-base b/.svn/pristine/1b/1b511d8dc10711a9b500c6dea251529f59d249f0.svn-base
new file mode 100644
index 0000000..316ff00
--- /dev/null
+++ b/.svn/pristine/1b/1b511d8dc10711a9b500c6dea251529f59d249f0.svn-base
@@ -0,0 +1,35 @@
+### 窗口周期计数器
+窗口周期计数类,用于记录一个窗口周期数量,并且触发某个操作的场景。
+在下一个窗口周期会自动重置次数
+
+#### =======================>使用方法说明<=========================
+
+1.引入包
+2.构造对象并次有
+3.调用对象的增加次数方法
+
+```go
+package demo
+
+import (
+ "time"
+
+ "goutil/counter_util"
+)
+
+func main() {
+ // 构造名字叫test的,窗口间隔为1s,计数达到2就会触发警告的窗口计数器
+ c := counter_util.NewCounterUtil("test", 2, checkId, func(tag string, num int, ti time.Time) {
+ //自定义触发动作
+ })
+
+ c.AddNum(1)
+ c.AddNum(10)
+}
+
+// 窗口周期设定为1s
+func checkId(t1, t2 time.Time) bool {
+ return t1.Second() == t2.Second()
+}
+
+```
\ No newline at end of file
diff --git a/.svn/pristine/1b/1bb1d81f707f332983e7042674e7c933e71d089e.svn-base b/.svn/pristine/1b/1bb1d81f707f332983e7042674e7c933e71d089e.svn-base
new file mode 100644
index 0000000..368103f
--- /dev/null
+++ b/.svn/pristine/1b/1bb1d81f707f332983e7042674e7c933e71d089e.svn-base
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "common/connection"
+ "sync"
+
+ _ "common/resultStatus"
+ "common/webServer"
+ _ "logincenter/internal/user"
+)
+
+var (
+ wg sync.WaitGroup
+)
+
+func init() {
+ // 设置WaitGroup需要等待的数量,只要有一个服务器出现错误都停止服务器
+ wg.Add(1)
+}
+
+func main() {
+
+ //加载配置
+ loadConfig()
+
+ // 启动webserver
+ go webServer.Start(&wg)
+
+ // 阻塞等待,以免main线程退出
+ wg.Wait()
+}
+
+// loadConfig 用于加载配置信息。
+// 该函数会读取配置文件或环境变量中的设置,并根据这些设置初始化程序所需的配置。
+// 目前函数的实现为空,需要根据实际的配置加载逻辑进行填充。
+func loadConfig() {
+
+ //构建数据库
+ connection.BuildDB()
+}
diff --git a/.svn/pristine/1b/1bdd83307433453f47a849b07a75501b86ac53eb.svn-base b/.svn/pristine/1b/1bdd83307433453f47a849b07a75501b86ac53eb.svn-base
new file mode 100644
index 0000000..affa8ca
--- /dev/null
+++ b/.svn/pristine/1b/1bdd83307433453f47a849b07a75501b86ac53eb.svn-base
@@ -0,0 +1,36 @@
+module logincenter
+
+go 1.22.10
+
+replace (
+ common => ../common
+ framework => ../../framework
+ goutil => ../../goutil
+)
+
+require common v0.0.0-00010101000000-000000000000
+
+require (
+ filippo.io/edwards25519 v1.1.0 // indirect
+ framework v0.0.0-20230425160006-b2d0b0a0b0b0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+ github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4 // indirect
+ github.com/fatih/color v1.15.0 // indirect
+ github.com/go-redis/redis/v8 v8.11.5 // indirect
+ github.com/go-sql-driver/mysql v1.8.1 // indirect
+ github.com/gomodule/redigo v1.8.9 // indirect
+ github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/jinzhu/gorm v1.9.12 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.17 // indirect
+ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
+ golang.org/x/sys v0.6.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
+ gorm.io/driver/mysql v1.5.7 // indirect
+ gorm.io/gorm v1.25.12 // indirect
+ goutil v0.0.0-20230425160006-b2d0b0a0b0b0 // indirect
+)
diff --git a/.svn/pristine/1b/1bf0ed25a847601c48c478898d552ab339455646.svn-base b/.svn/pristine/1b/1bf0ed25a847601c48c478898d552ab339455646.svn-base
new file mode 100644
index 0000000..681aa64
--- /dev/null
+++ b/.svn/pristine/1b/1bf0ed25a847601c48c478898d552ab339455646.svn-base
@@ -0,0 +1,6 @@
+package verifyMgr
+
+/*
+此包用于对指定url进行访问验证,以便于在程序启动时可以提前知道目标地址的可访问性,
+而不用等到实际需要时再验证;从而造成既定的影响。
+*/
diff --git a/.svn/pristine/1c/1cb4f4122548d93244351bbac432d4a7cdde9667.svn-base b/.svn/pristine/1c/1cb4f4122548d93244351bbac432d4a7cdde9667.svn-base
new file mode 100644
index 0000000..610a0e8
--- /dev/null
+++ b/.svn/pristine/1c/1cb4f4122548d93244351bbac432d4a7cdde9667.svn-base
@@ -0,0 +1,22 @@
+package sensitiveWordsMgr
+
+import (
+ "testing"
+)
+
+// type Persion struct {
+// name string
+// }
+
+// 屏蔽字详细信息
+func Test1(t *testing.T) {
+ //启动获取敏感字
+ refreshSensitiveWord()
+
+ words, pos, exist := SensitiveWords("测试,测试")
+ if exist {
+ t.Log(words, pos)
+ }
+
+ t.Log("END")
+}
diff --git a/.svn/pristine/1c/1cbdbfc80bd20fd584e9675d554ea02cb7d35caa.svn-base b/.svn/pristine/1c/1cbdbfc80bd20fd584e9675d554ea02cb7d35caa.svn-base
new file mode 100644
index 0000000..1da475a
--- /dev/null
+++ b/.svn/pristine/1c/1cbdbfc80bd20fd584e9675d554ea02cb7d35caa.svn-base
@@ -0,0 +1,377 @@
+package utils
+
+import (
+ "bytes"
+ "compress/flate"
+ "encoding/json"
+ "fmt"
+ "goutil/logUtilPlus"
+ "io/ioutil"
+ "math/rand"
+ "net/http"
+ "runtime/debug"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// 定义常量
+var MinDateTime = time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
+var MaxDateTime = time.Date(3000, 1, 1, 0, 0, 0, 0, time.Local)
+var GuidEmpty = "00000000-0000-0000-0000-000000000000"
+
+// IsTrue
+// @description: 是否为true
+// parameter:
+// @data: []byte格式的bool信息
+// return:
+// @bool: 返回布尔值
+func IsTrue(data []byte) bool {
+
+ if data == nil {
+ return false
+ }
+
+ if len(data) == 0 {
+ return false
+ }
+
+ if data[0] == 0 {
+ return false
+ } else {
+ return true
+ }
+}
+
+// ConvertBooleanToBytes
+// @description: bool型转换成byte数组
+// parameter:
+// @status: 状态
+// return:
+// @[]byte: 返回字节数组
+func ConvertBooleanToBytes(status bool) []byte {
+
+ if status == false {
+ return []byte{0}
+ } else {
+ return []byte{1}
+ }
+}
+
+// StrSliceJoinToStr
+// @description: 将[]string组装成字符串
+// parameter:
+// @numArray: 源int32数组
+// @sep: 分割字符串
+// return:
+// @string: 组成的字符串
+func StrSliceJoinToStr(numArray []string, sep string) string {
+ str := ""
+ if numArray == nil || len(numArray) == 0 {
+ return str
+ }
+
+ for _, n := range numArray {
+ str += fmt.Sprintf("%s%s", n, sep)
+ }
+
+ str = strings.TrimSuffix(str, sep)
+
+ return str
+}
+
+// Int32SliceJoinToStr
+// @description: 将[]int32转换成字符串
+// parameter:
+// @source: 资源
+// @sep: 分隔符
+// return:
+// @result: 字符串
+func Int32SliceJoinToStr(source []int32, sep string) (result string) {
+ if source == nil || len(source) == 0 {
+ return ""
+ }
+
+ for _, s := range source {
+ result += fmt.Sprintf("%d%s", s, sep)
+ }
+
+ result = strings.TrimRight(result, sep)
+
+ return
+}
+
+// SplitToStrSlice
+// @description: 将字符串切割为[]string
+// parameter:
+// @s: 输入字符串
+// @sep: 分割字符串
+// @removeEmpty: 是否去除空字符串
+// return:
+// @resultSlice: 字符串列表
+func SplitToStrSlice(s, sep string, removeEmpty bool) (resultSlice []string) {
+ if len(s) == 0 {
+ return make([]string, 0)
+ }
+
+ // 先按照分隔符进行切割
+ strSlice := strings.Split(s, sep)
+
+ for _, value := range strSlice {
+ if removeEmpty {
+ // 去除空格
+ if value = strings.TrimSpace(value); value == "" {
+ continue
+ }
+ }
+
+ resultSlice = append(resultSlice, value)
+ }
+
+ return resultSlice
+}
+
+// ParseTimeString
+// @description: 解析时间字符串
+// parameter:
+// @timeStr: 时间字符串,例:12:33:12
+// return:
+// @hour: 小时
+// @minute: 分钟
+// @second: 秒数
+func ParseTimeString(timeStr string) (hour int, minute int, second int) {
+ timeSlice := strings.Split(timeStr, ":")
+ if len(timeSlice) != 3 {
+ return
+ }
+
+ hour, _ = strconv.Atoi(timeSlice[0])
+ minute, _ = strconv.Atoi(timeSlice[1])
+ second, _ = strconv.Atoi(timeSlice[2])
+
+ return
+}
+
+// Rm_duplicate_string
+// @description: 去重
+// parameter:
+// @list: 列表
+// return:
+// @[]string: 去重后的数据
+func Rm_duplicate_string(list []string) []string {
+ var x []string = []string{}
+ for _, i := range list {
+ if len(x) == 0 {
+ x = append(x, i)
+ } else {
+ for k, v := range x {
+ if i == v {
+ break
+ }
+ if k == len(x)-1 {
+ x = append(x, i)
+ }
+ }
+ }
+ }
+ return x
+}
+
+// Rm_duplicate_int32
+// @description: 去重
+// parameter:
+// @list: 列表数据
+// return:
+// @[]int32: 去重后的结果
+func Rm_duplicate_int32(list []int32) []int32 {
+ var x []int32 = []int32{}
+ for _, i := range list {
+ if len(x) == 0 {
+ x = append(x, i)
+ } else {
+ for k, v := range x {
+ if i == v {
+ break
+ }
+ if k == len(x)-1 {
+ x = append(x, i)
+ }
+ }
+ }
+ }
+ return x
+}
+
+// RandomAarrayOfInt32
+// @description: int32数组乱序
+// parameter:
+// @arr: 数组
+// return:
+func RandomAarrayOfInt32(arr []int32) {
+
+ if arr == nil {
+ return
+ }
+
+ if len(arr) <= 0 {
+ return
+ }
+
+ rand.Seed(time.Now().UnixNano())
+
+ for i := len(arr) - 1; i > 0; i-- {
+ num := rand.Intn(i + 1)
+ arr[i], arr[num] = arr[num], arr[i]
+ }
+}
+
+// RandomAarrayOfString
+// @description: string数组乱序
+// parameter:
+// @arr: 数组
+// return:
+func RandomAarrayOfString(arr []string) {
+
+ if arr == nil {
+ return
+ }
+
+ if len(arr) <= 0 {
+ return
+ }
+
+ rand.Seed(time.Now().UnixNano())
+
+ for i := len(arr) - 1; i > 0; i-- {
+ num := rand.Intn(i + 1)
+ arr[i], arr[num] = arr[num], arr[i]
+ }
+}
+
+// LogErrorRecover
+// @description: 记录错误
+// parameter:
+// return:
+func LogErrorRecover() {
+ if err := recover(); err != nil {
+ tmsg := fmt.Sprintf("err msg:%s stack:%s", err, debug.Stack())
+ logUtilPlus.ErrorLog(tmsg)
+ }
+}
+
+// LogReqErrorRecover
+// @description: 记录错误
+// parameter:
+// @r:
+// return:
+func LogReqErrorRecover(r *http.Request) {
+ if err := recover(); err != nil {
+ b, err := json.Marshal(r)
+ reqStr := ""
+ if err == nil {
+ reqStr = string(b)
+ }
+ tmsg := fmt.Sprintf("RequestInfo:%s .err msg:%s stack:%s", reqStr, err, debug.Stack())
+ logUtilPlus.ErrorLog(tmsg)
+ }
+}
+
+// StringSliceIsExists
+// @description: StringSliceIsExists
+// parameter:
+// @strList: strList
+// @val: val
+// return:
+// @bool: 是否存在
+func StringSliceIsExists(strList []string, val string) bool {
+
+ if strList == nil {
+ return false
+ }
+
+ for _, v := range strList {
+ if v == val {
+ return true
+ }
+ }
+
+ return false
+}
+
+// Int64SliceIsExists
+// @description: Int64SliceIsExists
+// parameter:
+// @strList: strList
+// @val: val
+// return:
+// @bool: 是否存在
+func Int64SliceIsExists(strList []int64, val int64) bool {
+
+ if strList == nil {
+ return false
+ }
+
+ for _, v := range strList {
+ if v == val {
+ return true
+ }
+ }
+
+ return false
+}
+
+// SliceIsExists
+// @description: SliceIsExists
+// parameter:
+// @n: n
+// @f: f
+// return:
+// @bool: 是否存在
+func SliceIsExists(n int, f func(int) bool) bool {
+
+ for i := 0; i < n; i++ {
+ if f(i) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// FlateEncode
+// @description: 压缩字符串
+// parameter:
+// @input: 输入字符列表
+// return:
+// @result: 结果字符列表
+// @err: 错误信息
+func FlateEncode(input []byte) (result []byte, err error) {
+ var buf bytes.Buffer
+ w, err := flate.NewWriter(&buf, flate.DefaultCompression)
+ if err != nil {
+ return nil, err
+ }
+
+ // 无法使用defer close使用无法拿到结果
+ _, err = w.Write(input)
+ if err != nil {
+ return nil, err
+ }
+
+ w.Close()
+
+ result = buf.Bytes()
+ return
+}
+
+// FlateDecode
+// @description: FlateDecode
+// parameter:
+// @input: 输入字符列表
+// return:
+// @result: 结果字符列表
+// @err: 错误信息
+func FlateDecode(input []byte) (result []byte, err error) {
+ result, err = ioutil.ReadAll(flate.NewReader(bytes.NewReader(input)))
+ return
+}
diff --git a/.svn/pristine/1c/1cd69be06a95554c30263afa7ce43d3775f1dcdb.svn-base b/.svn/pristine/1c/1cd69be06a95554c30263afa7ce43d3775f1dcdb.svn-base
new file mode 100644
index 0000000..94cef04
--- /dev/null
+++ b/.svn/pristine/1c/1cd69be06a95554c30263afa7ce43d3775f1dcdb.svn-base
@@ -0,0 +1,34 @@
+package admin
+
+import (
+ "common/connection"
+)
+
+func init() {
+ //注册数据库
+ connection.RegisterDBModel(&Admin{})
+}
+
+type Admin struct {
+ ID int64 `gorm:"column:id;primary_key;comment:管理员id;autoIncrementIncrement" json:"id"`
+ //账号
+ Account string `gorm:"column:account;comment:账号" json:"account"`
+ Name string `gorm:"column:name;comment:管理员名称" json:"name"`
+ Password string `gorm:"column:password;comment:管理员密码" json:"password"`
+ //性别
+ Sex int32 `gorm:"column:sex;comment:性别" json:"sex"`
+ //生日
+ Birthday string `gorm:"column:birthday;comment:生日" json:"birthday"`
+ //手机
+ Phone int64 `gorm:"column:phone;comment:手机" json:"phone"`
+ //邮箱
+ Email string `gorm:"column:email;comment:邮箱" json:"email"`
+ //微信群【方便发送通知】
+ WechatGroup string `gorm:"column:wechat_group;comment:微信群" json:"wechat_group"`
+ //备注
+ Describe string `gorm:"column:describe;comment:备注" json:"describe"`
+}
+
+func (Admin) TableName() string {
+ return "admin"
+}
diff --git a/.svn/pristine/1c/1cd8027881b113926160df0087f10a47ea9e87ff.svn-base b/.svn/pristine/1c/1cd8027881b113926160df0087f10a47ea9e87ff.svn-base
new file mode 100644
index 0000000..4edafce
--- /dev/null
+++ b/.svn/pristine/1c/1cd8027881b113926160df0087f10a47ea9e87ff.svn-base
@@ -0,0 +1,62 @@
+package validationUtil
+
+import (
+ "testing"
+)
+
+// 身份证测试
+func TestIdCard(t *testing.T) {
+ idno := "450325197410077393"
+ if IsValideIdno(idno) == false {
+ t.Error("身份证验证出错:", idno)
+ t.Fail()
+ }
+ idno = "36062219701120774X"
+ if IsValideIdno(idno) == false {
+ t.Error("身份证验证出错:", idno)
+ t.Fail()
+ }
+ idno = "450325197410071111"
+ if IsValideIdno(idno) == false {
+ t.Error("身份证验证出错:", idno)
+ t.Fail()
+ }
+ idno = "3123123123"
+ if IsValideIdno(idno) == true {
+ t.Error("身份证验证出错:", idno)
+ t.Fail()
+ }
+}
+
+// 邮箱测试
+func TestMail(t *testing.T) {
+ mail := "nihao@qq.com"
+ if IsValideEmail(mail) == false {
+ t.Error("邮箱验证出错:", mail)
+ t.Fail()
+ }
+ mail = "111@qq.com"
+ if IsValideEmail(mail) == false {
+ t.Error("邮箱验证出错:", mail)
+ t.Fail()
+ }
+ mail = "111_@qq.com"
+ if IsValideEmail(mail) == false {
+ t.Error("邮箱验证出错:", mail)
+ t.Fail()
+ }
+}
+
+// 验证中国的手机号
+func TestChinesePhone(t *testing.T) {
+ phoneNum := "15111111111"
+ if IsValideChinesePhoneNum(phoneNum) == false {
+ t.Error("手机号验证出错:", phoneNum)
+ t.Fail()
+ }
+ phoneNum = "11111"
+ if IsValideChinesePhoneNum(phoneNum) == true {
+ t.Error("手机号验证出错:", phoneNum)
+ t.Fail()
+ }
+}
diff --git a/.svn/pristine/1c/1ce84cb99036df716050665854c27a1925523227.svn-base b/.svn/pristine/1c/1ce84cb99036df716050665854c27a1925523227.svn-base
new file mode 100644
index 0000000..32dfaf9
--- /dev/null
+++ b/.svn/pristine/1c/1ce84cb99036df716050665854c27a1925523227.svn-base
@@ -0,0 +1,137 @@
+package mysqlUtil
+
+import (
+ "database/sql"
+ "fmt"
+
+ _ "github.com/go-sql-driver/mysql"
+ "goutil/logUtil"
+)
+
+// 打开数据库连接
+// connectionString:数据库连接字符串,格式:root:moqikaka3306@tcp(10.1.0.10:3306)/gameserver_data?charset=utf8&parseTime=true&loc=Local&timeout=60s||MaxOpenConns=10||MaxIdleConns=5
+// 返回值:
+// 数据库对象
+// 错误对象
+func OpenMysqlConnection(connectionString string) (dbObj *sql.DB, err error) {
+ dbConfigObj, err1 := NewDBConfig2(connectionString)
+ if err1 != nil {
+ err = err1
+ return
+ }
+
+ dbObj, err = OpenMysqlConnection3(dbConfigObj)
+ return
+}
+
+// 打开数据库连接
+// connectionString:数据库连接字符串
+// maxOpenConns:最大打开的连接数
+// maxIdleConns:最大处于闲置状态的连接数
+// 返回值:
+// 数据库对象
+// 错误对象
+func OpenMysqlConnection2(connectionString string, maxOpenConns, maxIdleConns int) (dbObj *sql.DB, err error) {
+ dbConfigObj := NewDBConfig(connectionString, maxOpenConns, maxIdleConns)
+ dbObj, err = OpenMysqlConnection3(dbConfigObj)
+ return
+}
+
+// 建立Mysql数据库连接
+// dbConfigObj:数据库配置对象
+// 返回值:
+// 数据库对象
+// 错误对象
+func OpenMysqlConnection3(dbConfigObj *DBConfig) (dbObj *sql.DB, err error) {
+ // 建立数据库连接
+ logUtil.DebugLog("开始连接Mysql数据库")
+ dbObj, err = sql.Open("mysql", dbConfigObj.ConnectionString)
+ if err != nil {
+ err = fmt.Errorf("打开游戏数据库失败,连接字符串为:%s", dbConfigObj.ConnectionString)
+ return
+ }
+ logUtil.DebugLog("连接Mysql数据库成功")
+
+ if dbConfigObj.MaxOpenConns > 0 && dbConfigObj.MaxIdleConns > 0 {
+ dbObj.SetMaxOpenConns(dbConfigObj.MaxOpenConns)
+ dbObj.SetMaxIdleConns(dbConfigObj.MaxIdleConns)
+ }
+
+ if err = dbObj.Ping(); err != nil {
+ err = fmt.Errorf("Ping数据库失败,连接字符串为:%s,错误信息为:%s", dbConfigObj.ConnectionString, err)
+ return
+ }
+
+ return
+}
+
+// 测试数据库连接
+// dbObj:数据库连对象
+// 返回值:
+// 错误对象
+func TestConnection(dbObj *sql.DB) error {
+ command := "SHOW DATABASES;"
+ rows, err := dbObj.Query(command)
+ if err != nil {
+ return err
+ }
+
+ defer rows.Close()
+
+ return nil
+}
+
+// 开始事务
+// db:数据库对象
+// 返回值:
+// 事务对象
+// 错误对象
+func BeginTransaction(dbObj *sql.DB) (*sql.Tx, error) {
+ tx, err := dbObj.Begin()
+ if err != nil {
+ logUtil.Log(fmt.Sprintf("开启事务失败,错误信息:%s", err), logUtil.Error, true)
+ }
+
+ return tx, err
+}
+
+// 提交事务
+// tx:事务对象
+// 返回值:
+// 错误对象
+func CommitTransaction(tx *sql.Tx) error {
+ err := tx.Commit()
+ if err != nil {
+ logUtil.Log(fmt.Sprintf("提交事务失败,错误信息:%s", err), logUtil.Error, true)
+ }
+
+ return err
+}
+
+// 记录Prepare错误
+// command:执行的SQL语句
+// err:错误对象
+func WritePrepareError(command string, err error) {
+ logUtil.Log(fmt.Sprintf("Prepare失败,错误信息:%s,command:%s", err, command), logUtil.Error, true)
+}
+
+// 记录Query错误
+// command:执行的SQL语句
+// err:错误对象
+func WriteQueryError(command string, err error) {
+ logUtil.Log(fmt.Sprintf("Query失败,错误信息:%s,command:%s", err, command), logUtil.Error, true)
+}
+
+// 记录Exec错误
+// command:执行的SQL语句
+// err:错误对象
+func WriteExecError(command string, err error) {
+ logUtil.Log(fmt.Sprintf("Exec失败,错误信息:%s,command:%s", err, command), logUtil.Error, true)
+}
+
+// 记录Scan错误
+// command:执行的SQL语句
+// err:错误对象
+func WriteScanError(command string, err error) {
+ logUtil.Log(fmt.Sprintf("Scan失败,错误信息:%s,command:%s", err, command), logUtil.Error, true)
+}
diff --git a/.svn/pristine/1d/1d02ea53e36d220fc9a9e9944b67bc4d96bd8d26.svn-base b/.svn/pristine/1d/1d02ea53e36d220fc9a9e9944b67bc4d96bd8d26.svn-base
new file mode 100644
index 0000000..02eaad6
--- /dev/null
+++ b/.svn/pristine/1d/1d02ea53e36d220fc9a9e9944b67bc4d96bd8d26.svn-base
@@ -0,0 +1,20 @@
+coroutine-timer支持如下工作:
+定时触发设定的回调,最小精度秒级
+
+## 使用方式
+
+### 增加回调
+
+> 1. 导入包
+> 2. 调用AddTimerx添加定时回调,传入相关参数
+
+ps:
+> 1. AddTimer1,AddTimer2,AddTimer3是内部自动生成的id,内部保证唯一性。外部如果后续要删除该添加的timer,需要持有返回的id信息
+> 2. AddTimer4 需要外部传入id,外部需要保证id的唯一性。并且这个方法会在内部校验id是否已经存在,所以性能上会比其他AddTimer方法慢
+
+### 删除回调
+
+```go
+ DeleteTimer(id)
+```
+
diff --git a/.svn/pristine/1d/1d4e0f007677509afe5a28cf69b7241d9675e0c1.svn-base b/.svn/pristine/1d/1d4e0f007677509afe5a28cf69b7241d9675e0c1.svn-base
new file mode 100644
index 0000000..e209ebf
--- /dev/null
+++ b/.svn/pristine/1d/1d4e0f007677509afe5a28cf69b7241d9675e0c1.svn-base
@@ -0,0 +1,82 @@
+package main
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "goutil/mathUtil"
+ "goutil/stringUtil"
+)
+
+var (
+ wg sync.WaitGroup
+)
+
+func init() {
+ wg.Add(1)
+}
+
+func main() {
+ playerMgr := newPlayerMgr()
+
+ // insert
+ go func() {
+ for {
+ id := stringUtil.GetNewGUID()
+ name := fmt.Sprintf("Hero_%s", id)
+ obj := newPlayer(id, name)
+ playerMgr.insert(obj)
+
+ insert(obj)
+ time.Sleep(10 * time.Millisecond)
+ }
+ }()
+
+ // update
+ go func() {
+ for {
+ obj := playerMgr.randomSelect()
+ if obj == nil {
+ continue
+ }
+ suffix := mathUtil.GetRand().GetRandInt(1000)
+ newName := fmt.Sprintf("Hero_%d", suffix)
+ obj.resetName(newName)
+
+ update(obj)
+ time.Sleep(10 * time.Millisecond)
+ }
+ }()
+
+ // delete
+ go func() {
+ for {
+ obj := playerMgr.randomSelect()
+ if obj == nil {
+ continue
+ }
+ playerMgr.delete(obj)
+
+ clear(obj)
+ time.Sleep(10 * time.Millisecond)
+ }
+ }()
+
+ // errorFile
+ go func() {
+ for {
+ time.Sleep(1 * time.Hour)
+ id := stringUtil.GetNewGUID()
+ name := fmt.Sprintf("Hero_%s%s", id, id)
+ obj := newPlayer(id, name)
+ playerMgr.insert(obj)
+ print("errorFile")
+
+ insert(obj)
+ }
+
+ }()
+
+ wg.Wait()
+}
diff --git a/.svn/pristine/21/213b0a00bea424ffed61b3775e9a3885c7c78fac.svn-base b/.svn/pristine/21/213b0a00bea424ffed61b3775e9a3885c7c78fac.svn-base
new file mode 100644
index 0000000..f093bfa
--- /dev/null
+++ b/.svn/pristine/21/213b0a00bea424ffed61b3775e9a3885c7c78fac.svn-base
@@ -0,0 +1,219 @@
+package dfaUtil
+
+import "strings"
+
+/*
+DFA util, is used to verify whether a sentence has invalid words.
+The underlying data structure is trie.
+https://en.wikipedia.org/wiki/Trie
+*/
+
+// dfa util
+type DFAUtil struct {
+ // The root node
+ root *trieNode
+}
+
+// 搜索语句
+// 由于go不支持tuple,所以为了避免定义多余的struct,特别使用两个list来分别返回匹配的索引的上界和下界
+// 在处理此方法的返回值时,需要两者配合使用
+// 参数:
+//
+// sentence:语句字符串
+//
+// 返回:
+//
+// 搜索到的开始位置列表
+// 搜索到的结束位置列表
+func (this *DFAUtil) SearchSentence(sentence string) (startIndexList, endIndexList []int) {
+ sentenceRuneList := []rune(sentence)
+ for i := 0; i < len(sentenceRuneList); {
+ //按序匹配每个字
+ end := this.searchSentenceByStart(i, sentenceRuneList)
+ if end < 0 {
+ //匹配失败,继续匹配下一个字
+ i++
+ } else {
+ //匹配成功,记录索引位置
+ startIndexList = append(startIndexList, i)
+ endIndexList = append(endIndexList, end)
+
+ //从匹配到的字后面开始找
+ i = end + 1
+ }
+ }
+
+ return
+}
+
+// 从指定的开始位置搜索语句
+// 参数:
+//
+// start:开始匹配的位置
+// sentenceRuneList:语句字列表
+//
+// 返回:
+//
+// 匹配到的结束位置,未匹配到返回-1
+func (this *DFAUtil) searchSentenceByStart(start int, sentenceRuneList []rune) (endIndex int) {
+ //当前节点,从根节点开始找
+ currNode := this.root
+ //是否匹配到
+ var isMatched bool
+
+ //按顺序匹配字
+ for i := start; i < len(sentenceRuneList); {
+ child, exists := currNode.children[sentenceRuneList[i]]
+
+ //未匹配到则结束,跳出循环(可能匹配到过词结尾)
+ if !exists {
+ break
+ }
+
+ //是否是词末尾,如果是则先记录下来,因为还可能匹配到更长的词
+ //比如["金鳞"、"金鳞岂是池中物"] => 匹配"金鳞岂是池中物",匹配到"金鳞"不应该停下来,应继续匹配更长的词
+ if child.isEndOfWord {
+ endIndex = i
+ isMatched = true
+ }
+
+ //是否已经到词末尾
+ if len(child.children) == 0 {
+ return endIndex
+ } else {
+ //继续与后面的字匹配
+ currNode = child
+ }
+
+ //增加索引匹配下一个位置
+ i++
+ }
+
+ //匹配结束,若曾经匹配到词末尾,则直接返回匹配到的位置
+ if isMatched {
+ return endIndex
+ } else {
+ //没有匹配到词末尾,则返回匹配失败
+ return -1
+ }
+}
+
+// Insert new word into object
+func (this *DFAUtil) InsertWord(word []rune) {
+ currNode := this.root
+ for _, c := range word {
+ if cildNode, exist := currNode.children[c]; !exist {
+ cildNode = newtrieNode()
+ currNode.children[c] = cildNode
+ currNode = cildNode
+ } else {
+ currNode = cildNode
+ }
+ }
+
+ currNode.isEndOfWord = true
+}
+
+// Check if there is any word in the trie that starts with the given prefix.
+func (this *DFAUtil) StartsWith(prefix []rune) bool {
+ currNode := this.root
+ for _, c := range prefix {
+ if childNode, exist := currNode.children[c]; !exist {
+ return false
+ } else {
+ currNode = childNode
+ }
+ }
+
+ return true
+}
+
+// Judge if input sentence contains some special caracter
+// Return:
+// Matc or not
+func (this *DFAUtil) IsMatch(sentence string) bool {
+ startIndexList, _ := this.SearchSentence(sentence)
+ return len(startIndexList) > 0
+}
+
+// Handle sentence. Use specified caracter to replace those sensitive caracters.
+// input: Input sentence
+// replaceCh: candidate
+// Return:
+// Sentence after manipulation
+func (this *DFAUtil) HandleWord(sentence string, replaceCh rune) string {
+ startIndexList, endIndexList := this.SearchSentence(sentence)
+ if len(startIndexList) == 0 {
+ return sentence
+ }
+
+ // Manipulate
+ sentenceList := []rune(sentence)
+ for i := 0; i < len(startIndexList); i++ {
+ for index := startIndexList[i]; index <= endIndexList[i]; index++ {
+ sentenceList[index] = replaceCh
+ }
+ }
+
+ return string(sentenceList)
+}
+
+// Handle sentence. Use specified caracter to replace those sensitive caracters.
+// input: Input sentence
+// replaceCh: candidate
+// Return:
+// Sentence after manipulation
+func (this *DFAUtil) HandleWordUseStr(input string, replaceCh string) string {
+ input2 := strings.ToUpper(input)
+
+ startIndexList, endIndexList := this.SearchSentence(input2)
+ if len(startIndexList) == 0 {
+ return input
+ }
+
+ // Manipulate
+ inputRune := []rune(input)
+ replaceChList := []rune(replaceCh)
+
+ //上一次替换掉的数量
+ lastReplaceCount := 0
+
+ for i := 0; i < len(startIndexList); i++ {
+
+ //替换字的索引
+ index := len(replaceChList)
+
+ //开始位置--加上替换的词的索引
+ starIndex := startIndexList[i] + (i * index) - lastReplaceCount
+
+ //结束位置
+ endIndex := endIndexList[i] + (i * index) - lastReplaceCount
+
+ //结束字符串
+ sentenceAttr := string(inputRune[endIndex+1:])
+
+ //替换范围字符串
+ inputRune = append(inputRune[:starIndex], replaceChList...)
+ inputRune = append(inputRune, []rune(sentenceAttr)...)
+ lastReplaceCount = endIndex + 1 - starIndex
+ }
+
+ return string(inputRune)
+}
+
+// Create new DfaUtil object
+// wordList:word list
+func NewDFAUtil(wordList []string) *DFAUtil {
+ this := &DFAUtil{
+ root: newtrieNode(),
+ }
+
+ for _, word := range wordList {
+ wordRuneList := []rune(word)
+ if len(wordRuneList) > 0 {
+ this.InsertWord(wordRuneList)
+ }
+ }
+
+ return this
+}
diff --git a/.svn/pristine/21/21a7c96834766c7d74d55dbfaf1b49771fd9e489.svn-base b/.svn/pristine/21/21a7c96834766c7d74d55dbfaf1b49771fd9e489.svn-base
new file mode 100644
index 0000000..8a386c2
--- /dev/null
+++ b/.svn/pristine/21/21a7c96834766c7d74d55dbfaf1b49771fd9e489.svn-base
@@ -0,0 +1,54 @@
+# 配置根节点
+root:
+ # 是否是调试模式
+ debug: true
+
+ # Web服务监听地址和端口
+ web_server_address: "192.168.50.85:10052"
+
+ # Elasticsearch 地址
+ es_urls: "http://10.252.0.70:18099"
+
+ # 数据库配置
+ db_config:
+ admin_db:
+ # 最大处于开启状态的连接数
+ max_open_conns: 0
+
+ # 最大处于空闲状态的连接数
+ max_idle_conns: 0
+
+ # 数据库连接字符串
+ connection_string: "root:Qq5201530300@tcp(192.168.50.110:3306)/admin?charset=utf8&parseTime=true&loc=Local&timeout=30s&multiStatements=true"
+
+ user_db:
+ # 最大处于开启状态的连接数
+ max_open_conns: 0
+
+ # 最大处于空闲状态的连接数
+ max_idle_conns: 0
+
+ # 数据库连接字符串
+ connection_string: "root:Qq5201530300@tcp(192.168.50.110:3306)/user?charset=utf8&parseTime=true&loc=Local&timeout=30s&multiStatements=true"
+
+ redis_config:
+ # 数据库连接字符串
+ connection_string: "192.168.50.110:6379"
+
+ # 密码, 如果要设置用户Id,则密码设置为:"UserId:Password"
+ password: ""
+
+ # 数据库序号
+ database: 5
+
+ # 最大活跃连接数
+ max_active: 500
+
+ # 最大空闲的连接数
+ max_idle: 200
+
+ # 连接空闲超时时间,单位:秒
+ idle_timeout: 300
+
+ # 连接超时时间, 单位:秒
+ dial_connect_timeout: 10
\ No newline at end of file
diff --git a/.svn/pristine/21/21dc46aabd801627575e7862f59be14761f21a15.svn-base b/.svn/pristine/21/21dc46aabd801627575e7862f59be14761f21a15.svn-base
new file mode 100644
index 0000000..56a5d9b
--- /dev/null
+++ b/.svn/pristine/21/21dc46aabd801627575e7862f59be14761f21a15.svn-base
@@ -0,0 +1,123 @@
+package redisUtil
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Redis配置对象
+type RedisConfig struct {
+ // 连接字符串
+ ConnectionString string
+
+ // 密码
+ Password string
+
+ // 数据库编号
+ Database int
+
+ // 最大活跃连接数
+ MaxActive int
+
+ // 最大空闲连接数
+ MaxIdle int
+
+ // 空闲超时
+ IdleTimeout time.Duration
+
+ // 连接超时
+ DialConnectTimeout time.Duration
+}
+
+// 将redis连接字符串转化为redis config对象
+// 格式:ConnectionString=10.1.0.21:6379;Password=redis_pwd;Database=3;MaxActive=50;MaxIdle=20;IdleTimeout=300;DialConnectTimeout=10;
+// redisConfigStr:redis连接字符串
+// 返回值:
+// redis config对象
+// 错误对象
+func NewRedisConfig(redisConfigStr string) (redisConfig *RedisConfig, err error) {
+ var connectionString string
+ var password string
+ var database int
+ var maxActive int
+ var maxIdle int
+ var idleTimeout time.Duration
+ var dialConectTimeout time.Duration
+ var count int = 7
+ var subCount int = 2
+
+ itemList := strings.Split(redisConfigStr, ";")
+ // 去掉最后的空数据
+ if itemList[len(itemList)-1] == "" {
+ itemList = itemList[0 : len(itemList)-1]
+ }
+ if len(itemList) != count {
+ err = fmt.Errorf("%s格式不正确,需要包含%d个部分,现在有%d个部分", redisConfigStr, count, len(itemList))
+ return
+ }
+
+ for _, item := range itemList {
+ subItemList := strings.Split(item, "=")
+ if len(subItemList) != subCount {
+ err = fmt.Errorf("%s格式不正确,需要包含%d个部分", item, subCount)
+ return
+ }
+
+ // 分别进行判断
+ switch strings.ToLower(subItemList[0]) {
+ case strings.ToLower("ConnectionString"):
+ connectionString = subItemList[1]
+ case strings.ToLower("Password"):
+ password = subItemList[1]
+ case strings.ToLower("Database"):
+ if database, err = strconv.Atoi(subItemList[1]); err != nil {
+ err = fmt.Errorf("%s转化为int型失败", subItemList[1])
+ return
+ }
+ case strings.ToLower("MaxActive"):
+ if maxActive, err = strconv.Atoi(subItemList[1]); err != nil {
+ err = fmt.Errorf("%s转化为int型失败", subItemList[1])
+ return
+ }
+ case strings.ToLower("MaxIdle"):
+ if maxIdle, err = strconv.Atoi(subItemList[1]); err != nil {
+ err = fmt.Errorf("%s转化为int型失败", subItemList[1])
+ return
+ }
+ case strings.ToLower("IdleTimeout"):
+ if idleTimeout_int, err1 := strconv.Atoi(subItemList[1]); err1 != nil {
+ err = fmt.Errorf("%s转化为int型失败", subItemList[1])
+ return
+ } else {
+ idleTimeout = time.Duration(idleTimeout_int) * time.Second
+ }
+ case strings.ToLower("DialConnectTimeout"):
+ if dialConectTimeout_int, err1 := strconv.Atoi(subItemList[1]); err1 != nil {
+ err = fmt.Errorf("%s转化为int型失败", subItemList[1])
+ return
+ } else {
+ dialConectTimeout = time.Duration(dialConectTimeout_int) * time.Second
+ }
+ }
+ }
+
+ redisConfig = NewRedisConfig2(connectionString, password, database, maxActive, maxIdle, idleTimeout, dialConectTimeout)
+ return
+}
+
+func NewRedisConfig2(connectionString, password string,
+ database, maxActive, maxIdle int,
+ idleTimeout, dialConnectTimeout time.Duration) *RedisConfig {
+
+ return &RedisConfig{
+ ConnectionString: connectionString,
+ Password: password,
+ Database: database,
+ MaxActive: maxActive,
+ MaxIdle: maxIdle,
+ IdleTimeout: idleTimeout,
+ DialConnectTimeout: dialConnectTimeout,
+ }
+}
diff --git a/.svn/pristine/22/220fecaa6504067877bec738054b2ee97658da3d.svn-base b/.svn/pristine/22/220fecaa6504067877bec738054b2ee97658da3d.svn-base
new file mode 100644
index 0000000..e7e19ee
--- /dev/null
+++ b/.svn/pristine/22/220fecaa6504067877bec738054b2ee97658da3d.svn-base
@@ -0,0 +1,16 @@
+package mqMgr
+
+// 消息队列配置对象
+type QueueConfig struct {
+ // 地域
+ Region string
+
+ // 队列名称
+ QueueName string
+
+ // API密钥Id
+ SecretId string
+
+ // API密钥key
+ SecretKey string
+}
diff --git a/.svn/pristine/23/2323503bd48538f9d2f8b36722a664b308762e83.svn-base b/.svn/pristine/23/2323503bd48538f9d2f8b36722a664b308762e83.svn-base
new file mode 100644
index 0000000..b39c205
--- /dev/null
+++ b/.svn/pristine/23/2323503bd48538f9d2f8b36722a664b308762e83.svn-base
@@ -0,0 +1,16 @@
+package goroutineMgr
+
+/*
+goroutine的管理包,提供了对goroutine的监控机制
+对外提供的方法为:
+
+// 监控指定的goroutine
+Monitor(goroutineName string)
+
+// 只添加数量,不监控
+MonitorZero(goroutineName string)
+
+// 释放监控
+ReleaseMonitor(goroutineName string)
+
+*/
diff --git a/.svn/pristine/23/23cb9734e39cd278edd81f86a6b942d541ea2921.svn-base b/.svn/pristine/23/23cb9734e39cd278edd81f86a6b942d541ea2921.svn-base
new file mode 100644
index 0000000..83a6660
--- /dev/null
+++ b/.svn/pristine/23/23cb9734e39cd278edd81f86a6b942d541ea2921.svn-base
@@ -0,0 +1,133 @@
+package handleMgr
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+ "time"
+)
+
+// ---------------申请示例实例--------------
+var (
+ data = make(map[int]int, 0)
+)
+
+type testBll struct {
+}
+
+// TestAdd
+// @description:测试添加
+// parameter:
+// @receiver t:
+// @x:
+// @y:
+// return:
+// @*ResponseObject:
+func (t testBll) TestAdd(x, y int) *ResponseObject {
+ responseObj := GetInitResponseObj()
+ data[x] = y
+ z := x + y
+
+ print(x)
+
+ responseObj.SetData(z)
+ responseObj.SetResultStatus(-11111, "错误码")
+ return responseObj
+}
+
+// See1
+// @description:测试添加
+// parameter:
+// @receiver t:
+// @x:
+// return:
+// @*ResponseObject:
+func (t testBll) See1(x int) *ResponseObject {
+ responseObj := GetInitResponseObj()
+ fmt.Print(x)
+ return responseObj
+}
+
+// See2
+// @description:测试添加
+// parameter:
+// @receiver t:
+// @x:
+// return:
+// @*ResponseObject:
+func (t testBll) See2(x int) *ResponseObject {
+ responseObj := GetInitResponseObj()
+ time.Sleep(2000 * time.Millisecond)
+ fmt.Print(x)
+ return responseObj
+}
+
+func (t testBll) ReMove(x int) *ResponseObject {
+ responseObj := GetInitResponseObj()
+ delete(data, x)
+ return responseObj
+}
+
+// ---------------测试方法--------------
+func TestNew(t *testing.T) {
+
+ var paramItem interface{}
+ paramItem = 123
+ paramFloat64, ok := paramItem.(int)
+ if ok {
+ x := reflect.ValueOf(int(paramFloat64))
+ t.Log(x)
+ }
+ t.Log(paramFloat64)
+ t.Log(ok)
+
+ //t.Log("A")
+ //RegisterNewModule("test", new(testBll), 10)
+
+ //parameter := []interface{}{"1", 2}
+ //x, y, mes := Done("test", "testBll", "TestAdd", parameter, false)
+ //for key, item := range data {
+ // t.Log(key, item)
+ //}
+
+ //t.Log("B2")
+ //parameter1 := []interface{}{2, 2}
+ //x, y, mes = Done("test", "testBll", "TestAdd", parameter1, true)
+ //for key, item := range data {
+ // t.Log(key, item)
+ //}
+ //t.Log(x)
+ //t.Log(y)
+ //t.Log(mes)
+ //t.Log("B3")
+ //
+ //t.Log("C")
+ //parameter2 := []interface{}{2}
+ //Done("test", "testBll", "ReMove", parameter2, true)
+ //for key, item := range data {
+ // t.Log(key, item)
+ //}
+ //t.Log("D")
+ //
+ //t.Log(time.Now().UnixMilli())
+ //parameter3 := []interface{}{1}
+ //Done("test", "testBll", "See2", parameter3, false)
+ //t.Log(time.Now().UnixMilli())
+ //parameter4 := []interface{}{2}
+ //Done("test", "testBll", "See1", parameter4, true)
+ //t.Log(time.Now().UnixMilli())
+ //parameter5 := []interface{}{1}
+ //Done("test", "testBll", "See1", parameter5, true)
+ //t.Log(time.Now().UnixMilli())
+ //
+ //t.Log("E")
+ //
+ //t.Log(time.Now().UnixMilli())
+ //for i := 0; i < 1000; i++ {
+ // Done("test", "testBll", "See1", parameter5, true)
+ //}
+ //t.Log(time.Now().UnixMilli())
+ //t.Log("F")
+
+ t.Error("G")
+}
diff --git a/.svn/pristine/24/2408308d2e72184a45660ed9c67c714a06107c62.svn-base b/.svn/pristine/24/2408308d2e72184a45660ed9c67c714a06107c62.svn-base
new file mode 100644
index 0000000..c73ae18
--- /dev/null
+++ b/.svn/pristine/24/2408308d2e72184a45660ed9c67c714a06107c62.svn-base
@@ -0,0 +1,109 @@
+package qcloud
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "time"
+
+ "goutil/mathUtil"
+ "goutil/webUtil"
+)
+
+const (
+ VOICE_CAPTCHA_URL = "https://cloud.tim.qq.com/v5/tlsvoicesvr/sendcvoice"
+ VOICE_NOTIFICATION_URL = "https://cloud.tim.qq.com/v5/tlsvoicesvr/sendvoiceprompt"
+ VOICE_TEMPLATE_NOTIFICATION_URL = "https://cloud.tim.qq.com/v5/tlsvoicesvr/sendtvoice"
+)
+
+// calculate sign-string for phone numbers
+func calcSig(appKey string, rand int, timeStamp int64, mobile string) string {
+ sum := sha256.Sum256([]byte(fmt.Sprintf("appkey=%s&random=%d&time=%d&mobile=%s", appKey, rand, timeStamp, mobile)))
+ return hex.EncodeToString(sum[:])
+}
+
+// do the http request and parse the response
+func request(url string, data map[string]interface{}, appId string, rand int) (success bool, err error) {
+ url = fmt.Sprintf("%s?sdkappid=%s&random=%d", url, appId, rand)
+ fmt.Printf("url:%s\n", url)
+
+ contentBytes, err := json.Marshal(data)
+ if err != nil {
+ return
+ }
+
+ fmt.Printf("data:%v\n", string(contentBytes))
+
+ _, retBytes, err := webUtil.PostByteData2(url, contentBytes, nil, nil)
+ if err != nil {
+ return
+ }
+
+ var responseObj *response
+ err = json.Unmarshal(retBytes, &responseObj)
+ if err != nil {
+ return
+ }
+ if responseObj.Result != 0 {
+ err = fmt.Errorf(responseObj.ErrMsg)
+ return
+ }
+
+ success = true
+ return
+}
+
+func SendVoiceCaptcha(appId, appKey, nation, mobile, captcha string, playTimes int) (success bool, err error) {
+ rand := mathUtil.GetRand().GetRandRangeInt(100000, 999999)
+ timeStamp := time.Now().Unix()
+
+ data := make(map[string]interface{})
+ data["playtimes"] = playTimes
+ data["sig"] = calcSig(appKey, rand, timeStamp, mobile)
+ data["tel"] = newTelField(nation, mobile)
+ data["time"] = timeStamp
+ data["ext"] = ""
+ // dedicated param
+ data["msg"] = captcha
+
+ success, err = request(VOICE_CAPTCHA_URL, data, appId, rand)
+ return
+}
+
+func SendVoiceNotification(appId, appKey, nation, mobile, prompt string, playTimes int) (success bool, err error) {
+ rand := mathUtil.GetRand().GetRandRangeInt(100000, 999999)
+ timeStamp := time.Now().Unix()
+ promptType := 2
+
+ data := make(map[string]interface{})
+ data["playtimes"] = playTimes
+ data["sig"] = calcSig(appKey, rand, timeStamp, mobile)
+ data["tel"] = newTelField(nation, mobile)
+ data["time"] = timeStamp
+ data["ext"] = ""
+ // dedicated param
+ data["promptfile"] = prompt
+ data["prompttype"] = promptType
+
+ success, err = request(VOICE_NOTIFICATION_URL, data, appId, rand)
+ return
+}
+
+func SendVoiceTemplateNotification(appId, appKey, nation, mobile string, templateId int, params []string, playTimes int) (success bool, err error) {
+ rand := mathUtil.GetRand().GetRandRangeInt(100000, 999999)
+ timeStamp := time.Now().Unix()
+
+ data := make(map[string]interface{})
+ data["playtimes"] = playTimes
+ data["sig"] = calcSig(appKey, rand, timeStamp, mobile)
+ data["tel"] = newTelField(nation, mobile)
+ data["time"] = timeStamp
+ data["ext"] = ""
+ // dedicated param
+ data["tpl_id"] = templateId
+ data["params"] = params
+
+ success, err = request(VOICE_TEMPLATE_NOTIFICATION_URL, data, appId, rand)
+ return
+}
diff --git a/.svn/pristine/24/242c687d5a16af36ce250d440564fc2b747e6dd4.svn-base b/.svn/pristine/24/242c687d5a16af36ce250d440564fc2b747e6dd4.svn-base
new file mode 100644
index 0000000..1f8c312
--- /dev/null
+++ b/.svn/pristine/24/242c687d5a16af36ce250d440564fc2b747e6dd4.svn-base
@@ -0,0 +1,79 @@
+package gameServerMgr
+
+import (
+ "time"
+
+ . "Framework/managecenterModel"
+ "goutil/timeUtil"
+ "goutil/typeUtil"
+)
+
+var (
+ mServerGroupObj *ServerGroup
+)
+
+//解析服务器组信息
+func ParseServerGroupInfo(serverGroupObj *ServerGroup) {
+ mServerGroupObj = serverGroupObj
+}
+
+//获取服务器组对象
+func GetServerGroup() (serverGroupObj *ServerGroup) {
+ serverGroupObj = mServerGroupObj
+
+ return
+}
+
+//检查服务器是否在维护
+func CheckMaintainStatus() (maintainMessage string, isMaintaining bool) {
+ serverGroupObj := GetServerGroup()
+ nowTick := time.Now().Unix()
+ if serverGroupObj.GroupState == int32(Con_GroupState_Maintain) || (serverGroupObj.MaintainBeginTimeTick <= nowTick && nowTick <= serverGroupObj.MaintainBeginTimeTick+int64(60*serverGroupObj.MaintainMinutes)) {
+ maintainMessage = serverGroupObj.MaintainMessage
+ isMaintaining = true
+
+ return
+ }
+
+ return
+}
+
+//获取服务器维护开始时间时间戳
+func GetMaintainBeginTime() (maintainBeginTimeTick int64) {
+ serverGroupObj := GetServerGroup()
+ maintainBeginTimeTick = serverGroupObj.MaintainBeginTimeTick
+
+ return
+}
+
+//获取服务器维护持续时间 单位分钟
+func GetMaintainMinutes() (maintainMinutes int32) {
+ serverGroupObj := GetServerGroup()
+ maintainMinutes = serverGroupObj.MaintainMinutes
+
+ return
+}
+
+//获取服务器开服日期 时间戳
+func GetServerOpenDate() (openTimeTick int64) {
+ serverGroupObj := GetServerGroup()
+ openTimeTick = serverGroupObj.OpenTimeTick
+
+ return
+}
+
+//当前服务器已开服天数(开服第几天)
+//当前开服天数 计算公式:(当前日期 - 开服日期)的总天数 + 1
+func ServerOpenDays() (days int32) {
+ serverGroupObj := GetServerGroup()
+ if serverGroupObj.IsOpen() == false {
+ return 0
+ }
+
+ //(当前日期 - 开服日期)的总天数 + 1
+ openTimeTick := serverGroupObj.OpenTimeTick
+ openDate, _ := typeUtil.DateTime(openTimeTick)
+ days = int32(timeUtil.SubDay(time.Now(), openDate) + 1)
+
+ return
+}
diff --git a/.svn/pristine/24/24d43d9907392c148b50ae48efa6d7f9e9746822.svn-base b/.svn/pristine/24/24d43d9907392c148b50ae48efa6d7f9e9746822.svn-base
new file mode 100644
index 0000000..18cd929
--- /dev/null
+++ b/.svn/pristine/24/24d43d9907392c148b50ae48efa6d7f9e9746822.svn-base
@@ -0,0 +1,225 @@
+package syncUtil
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "testing"
+ "time"
+)
+
+func TestMutex(t *testing.T) {
+ mu := NewMutex()
+ mu.Lock()
+ defer mu.UnLock()
+ if mu.TryLock() {
+ t.Errorf("cannot fetch mutex !!!")
+ }
+}
+
+func TestMutexTryLockTimeout(t *testing.T) {
+ fmt.Println("start")
+ mu := NewMutex()
+ mu.Lock()
+ go func() {
+ time.Sleep(20 * time.Second)
+ mu.UnLock()
+ }()
+ // if !mu.TryLockTimeout(500 * time.Microsecond) {
+ // t.Errorf("cannot fetch mutex in 500us !!!")
+ // }
+ if !mu.TryLockTimeout(15 * time.Second) {
+ t.Errorf("should fetch mutex in 5ms !!!")
+ }
+ mu.UnLock()
+}
+
+func TestMutexUnlockTwice(t *testing.T) {
+ mu := NewMutex()
+ mu.Lock()
+ defer func() {
+ if x := recover(); x != nil {
+ if x != "unlock of unlocked mutex" {
+ t.Errorf("unexpect panic")
+ }
+ } else {
+ t.Errorf("should panic after unlock twice")
+ }
+ }()
+ mu.UnLock()
+ mu.UnLock()
+}
+
+func TestMutexTryLockContext(t *testing.T) {
+ mu := NewMutex()
+ ctx, cancel := context.WithCancel(context.Background())
+ mu.Lock()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ cancel()
+ }()
+ if mu.TryLockContext(ctx) {
+ t.Errorf("cannot fetch mutex !!!")
+ }
+}
+
+func BenchmarkMutex(b *testing.B) {
+ mu := NewMutex()
+ a := 0
+ c := 0
+ b.ReportAllocs()
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ mu.Lock()
+ a++
+ mu.UnLock()
+ mu.Lock()
+ c = a
+ mu.UnLock()
+ }
+ })
+ _ = a
+ _ = c
+}
+
+func TestMutexGroup(t *testing.T) {
+ mu := NewMutexGroup()
+ mu.Lock("g")
+ defer mu.UnLock("g")
+ if mu.TryLock("g") {
+ t.Errorf("cannot fetch mutex !!!")
+ }
+}
+
+func TestMutexGroupMutliWaitLock(t *testing.T) {
+ var (
+ wg sync.WaitGroup
+ mu = NewMutexGroup()
+ cn = 3
+ )
+
+ for i := 0; i < cn; i++ {
+ wg.Add(1)
+ go func() {
+ mu.Lock("h")
+ time.Sleep(1e7)
+ mu.UnLock("h")
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+
+ for i := 0; i < cn; i++ {
+ wg.Add(1)
+ go func() {
+ mu.Lock("g")
+ time.Sleep(1e7)
+ mu.UnLockAndFree("g")
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestMutexGroupUnLockAndFree(t *testing.T) {
+ var (
+ wg sync.WaitGroup
+ mu = NewMutexGroup()
+ mg = mu.(*mutexGroup)
+ )
+
+ for j := 1; j < 5; j++ {
+ for i := 0; i < j; i++ {
+ wg.Add(1)
+ go func() {
+ mu.Lock("h")
+ time.Sleep(1e6)
+ mu.UnLockAndFree("h")
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ mg.mu.Lock()
+ if _, ok := mg.group["h"]; ok {
+ t.Error("h mutex exist after UnLockAndFree")
+ }
+ mg.mu.Unlock()
+ }
+}
+
+func TestMutexGroupTryLockFailedAndUnLockAndFree(t *testing.T) {
+ var (
+ wg sync.WaitGroup
+ mu = NewMutexGroup()
+ mg = mu.(*mutexGroup)
+ )
+
+ for j := 1; j < 5; j++ {
+ for i := 0; i < j; i++ {
+ wg.Add(1)
+ go func() {
+ if mu.TryLock("h") {
+ time.Sleep(1e6)
+ mu.UnLockAndFree("h")
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ mg.mu.Lock()
+ if _, ok := mg.group["h"]; ok {
+ t.Error("h mutex exist after UnLockAndFree")
+ }
+ mg.mu.Unlock()
+ }
+}
+
+func TestMutexGroupTryLockTimeout(t *testing.T) {
+ mu := NewMutexGroup()
+ mu.Lock("g")
+ go func() {
+ time.Sleep(1 * time.Millisecond)
+ mu.UnLock("g")
+ }()
+ if mu.TryLockTimeout("g", 500*time.Microsecond) {
+ t.Errorf("cannot fetch mutex in 500us !!!")
+ }
+ if !mu.TryLockTimeout("g", 5*time.Millisecond) {
+ t.Errorf("should fetch mutex in 5ms !!!")
+ }
+ mu.UnLock("g")
+}
+
+func TestMutexGroupTryLockContext(t *testing.T) {
+ mu := NewMutexGroup()
+ ctx, cancel := context.WithCancel(context.Background())
+ mu.Lock("g")
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ cancel()
+ }()
+ if mu.TryLockContext("g", ctx) {
+ t.Errorf("cannot fetch mutex !!!")
+ }
+}
+
+func BenchmarkMutexGroup(b *testing.B) {
+ mu := NewMutexGroup()
+ a := 0
+ c := 0
+ b.ReportAllocs()
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ mu.Lock("g")
+ a++
+ mu.UnLock("g")
+ mu.Lock("g")
+ c = a
+ mu.UnLock("g")
+ }
+ })
+ _ = a
+ _ = c
+}
diff --git a/.svn/pristine/25/253842466dd2f7a93da426d59d796617815b5714.svn-base b/.svn/pristine/25/253842466dd2f7a93da426d59d796617815b5714.svn-base
new file mode 100644
index 0000000..19ce417
--- /dev/null
+++ b/.svn/pristine/25/253842466dd2f7a93da426d59d796617815b5714.svn-base
@@ -0,0 +1,1575 @@
+package redisUtil
+
+import (
+ "testing"
+ "time"
+)
+
+var (
+ redisPoolObj_set *RedisPool
+)
+
+func init() {
+ redisPoolObj_set = NewRedisPool("testPool", "10.1.0.21:6379", "redis_pwd", 5, 500, 200, 10*time.Second, 5*time.Second)
+}
+
+func TestSAdd(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 添加单个元素
+
+ redis> SADD bbs "discuz.net"
+ (integer) 1
+ */
+ key := "bbs"
+ value := "discuz.net"
+ expected := 1
+ got, err := redisPoolObj_set.SAdd(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 添加重复元素
+
+ redis> SADD bbs "discuz.net"
+ (integer) 0
+ */
+ expected = 0
+ got, err = redisPoolObj_set.SAdd(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ /*
+ # 添加多个元素
+
+ redis> SADD bbs "tianya.cn" "groups.google.com"
+ (integer) 2
+ */
+ expected = 2
+ got, err = redisPoolObj_set.SAdd(key, "tianya.cn", "groups.google.com")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ /*
+ redis> SMEMBERS bbs
+ 1) "discuz.net"
+ 2) "groups.google.com"
+ 3) "tianya.cn"
+ */
+ expected2 := []string{"discuz.net", "groups.google.com", "tianya.cn"}
+ got2_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+}
+
+func TestSIsMember(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ key := "joe's_movies"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key, "hi, lady", "Fast Five", "2012")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SMEMBERS joe's_movies
+ 1) "hi, lady"
+ 2) "Fast Five"
+ 3) "2012"
+ */
+ expected2 := []string{"hi, lady", "Fast Five", "2012"}
+ got2_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+
+ /*
+ redis> SISMEMBER joe's_movies "bet man"
+ (integer) 0
+ */
+ expected3 := false
+ value := "bet man"
+ got3, err := redisPoolObj_set.SIsMember(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %t, but now got %t", expected3, got3)
+ return
+ }
+
+ /*
+ redis> SISMEMBER joe's_movies "Fast Five"
+ (integer) 1
+ */
+ expected3 = true
+ value = "Fast Five"
+ got3, err = redisPoolObj_set.SIsMember(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %t, but now got %t", expected3, got3)
+ return
+ }
+
+}
+
+func TestSPop(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ key := "db"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key, "MySQL", "MongoDB", "Redis")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SMEMBERS db
+ 1) "MySQL"
+ 2) "MongoDB"
+ 3) "Redis"
+ */
+ expected2 := []string{"MySQL", "MongoDB", "Redis"}
+ got2_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+
+ /*
+ redis> SPOP db
+ "Redis"
+
+ redis> SMEMBERS db
+ 1) "MySQL"
+ 2) "MongoDB"
+ */
+ expected3 := make(map[string]struct{})
+ for _, item := range expected2 {
+ expected3[item] = struct{}{}
+ }
+ got3_interface, err := redisPoolObj_set.SPop(key)
+ if err != nil {
+ t.Fail()
+ }
+ got3, err := redisPoolObj_set.String(got3_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if _, exist := expected3[got3]; !exist {
+ t.Errorf("Expected to get one of key from %v, but now get %s.", expected3, got3)
+ return
+ }
+ delete(expected3, got3)
+
+ expected4 := make([]string, 0, len(expected3))
+ for k := range expected3 {
+ expected4 = append(expected4, k)
+ }
+
+ got4_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SPOP db
+ "MySQL"
+
+ redis> SMEMBERS db
+ 1) "MongoDB"
+ */
+
+ expected5 := make(map[string]struct{})
+ for _, item := range expected4 {
+ expected5[item] = struct{}{}
+ }
+ got5_interface, err := redisPoolObj_set.SPop(key)
+ if err != nil {
+ t.Fail()
+ }
+ got5, err := redisPoolObj_set.String(got5_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if _, exist := expected5[got5]; !exist {
+ t.Errorf("Expected to get one of key from %v, but now get %s.", expected5, got5)
+ return
+ }
+ delete(expected5, got5)
+
+ expected6 := make([]string, 0, len(expected5))
+ for k := range expected5 {
+ expected6 = append(expected6, k)
+ }
+
+ got6_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got6, err := redisPoolObj_set.Strings(got6_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected6, got6) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected6, got6)
+ return
+ }
+}
+
+func TestSRandMember(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 添加元素
+
+ redis> SADD fruit apple banana cherry
+ (integer) 3
+ */
+ key := "fruit"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key, "apple", "banana", "cherry")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 只给定 key 参数,返回一个随机元素
+
+ redis> SRANDMEMBER fruit
+ "cherry"
+ */
+ expected2 := make(map[string]struct{})
+ expected2["apple"] = struct{}{}
+ expected2["banana"] = struct{}{}
+ expected2["cherry"] = struct{}{}
+
+ count := 1
+ got2_interface, err := redisPoolObj_set.SRandMember(key, count)
+ if err != nil {
+ t.Fail()
+ }
+ got2_slice, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if len(got2_slice) != count {
+ t.Errorf("Expected to have %d items, but now get %d.", count, len(got2_slice))
+ return
+ }
+ got2 := got2_slice[0]
+ if _, exist := expected2[got2]; !exist {
+ t.Errorf("Expected length %s, but got %s", expected2, got2)
+ return
+ }
+
+ /*
+ # 给定 3 为 count 参数,返回 3 个随机元素
+ # 每个随机元素都不相同
+
+ redis> SRANDMEMBER fruit 3
+ 1) "apple"
+ 2) "banana"
+ 3) "cherry"
+ */
+ count = 3
+ expected3 := make([]string, 0, len(expected2))
+ for k := range expected2 {
+ expected3 = append(expected3, k)
+ }
+ got3_interface, err := redisPoolObj_set.SRandMember(key, count)
+ if err != nil {
+ t.Fail()
+ }
+ got3_slice, err := redisPoolObj_set.Strings(got3_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if len(got3_slice) != count {
+ t.Errorf("Expected to have %d items, but now get %d.", count, len(got3_slice))
+ return
+ }
+ if isTwoUnorderedSliceEqual(expected3, got3_slice) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected3, got3_slice)
+ return
+ }
+
+ /*
+ # 给定 -3 为 count 参数,返回 3 个随机元素
+ # 元素可能会重复出现多次
+
+ redis> SRANDMEMBER fruit -3
+ 1) "banana"
+ 2) "cherry"
+ 3) "apple"
+
+ # 如果 count 是整数,且大于等于集合基数,那么返回整个集合
+
+ redis> SRANDMEMBER fruit 10
+ 1) "apple"
+ 2) "banana"
+ 3) "cherry"
+
+ # 如果 count 是负数,且 count 的绝对值大于集合的基数
+ # 那么返回的数组的长度为 count 的绝对值
+
+ redis> SRANDMEMBER fruit -10
+ 1) "banana"
+ 2) "apple"
+ 3) "banana"
+ 4) "cherry"
+ 5) "apple"
+ 6) "apple"
+ 7) "cherry"
+ 8) "apple"
+ 9) "apple"
+ 10) "banana"
+
+ # SRANDMEMBER 并不会修改集合内容
+
+ redis> SMEMBERS fruit
+ 1) "apple"
+ 2) "cherry"
+ 3) "banana"
+
+ # 集合为空时返回 nil 或者空数组
+
+ redis> SRANDMEMBER not-exists
+ (nil)
+
+ redis> SRANDMEMBER not-eixsts 10
+ (empty list or set)
+ */
+}
+
+func TestSRem(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ // defer func() {
+ // // Delete the test keys
+ // distinctKeyList := getDistinctKeyList(deleteKeys)
+ // count, err := redisPoolObj_list.Del(distinctKeyList...)
+ // if err != nil {
+ // t.Fail()
+ // }
+ // if count != len(distinctKeyList) {
+ // t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ // return
+ // }
+ // }()
+
+ /*
+ # 添加元素
+
+ redis> SADD languages c lisp python ruby
+ (integer) 4
+ */
+ key := "languages"
+ expected := 4
+ got, err := redisPoolObj_set.SAdd(key, "c", "lisp", "python", "ruby")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 测试数据
+
+ redis> SMEMBERS languages
+ 1) "c"
+ 2) "lisp"
+ 3) "python"
+ 4) "ruby"
+ */
+ expected2 := make(map[string]struct{})
+ expected2["c"] = struct{}{}
+ expected2["lisp"] = struct{}{}
+ expected2["python"] = struct{}{}
+ expected2["ruby"] = struct{}{}
+
+ expected4 := make([]string, 0, len(expected2))
+ for k := range expected2 {
+ expected4 = append(expected4, k)
+ }
+
+ got4_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ # 移除单个元素
+
+ redis> SREM languages ruby
+ (integer) 1
+ */
+ value := "ruby"
+ expected5 := 1
+ got5, err := redisPoolObj_set.SRem(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got5 != expected5 {
+ t.Errorf("Expected length %d, but got %d", expected5, got5)
+ return
+ }
+
+ /*
+ # 移除不存在元素
+
+ redis> SREM languages non-exists-language
+ (integer) 0
+ */
+ value = "non-exists-language"
+ expected6 := 0
+ got6, err := redisPoolObj_set.SRem(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got6 != expected6 {
+ t.Errorf("Expected length %d, but got %d", expected6, got6)
+ return
+ }
+
+ /*
+ # 移除多个元素
+
+ redis> SREM languages lisp python c
+ (integer) 3
+
+ redis> SMEMBERS languages
+ (empty list or set)
+ */
+ expected7 := 3
+ got7, err := redisPoolObj_set.SRem(key, "c", "lisp", "python")
+ if err != nil {
+ t.Fail()
+ }
+ if got7 != expected7 {
+ t.Errorf("Expected length %d, but got %d", expected7, got7)
+ return
+ }
+
+ expected8 := make([]string, 0)
+ got8_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got8, err := redisPoolObj_set.Strings(got8_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected8, got8) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected8, got8)
+ return
+ }
+}
+
+func TestSMove(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 添加元素
+
+ redis> SADD languages c lisp python ruby
+ (integer) 4
+ */
+ source := "songs"
+ expected := 2
+ got, err := redisPoolObj_set.SAdd(source, "Billie Jean", "Believe Me")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, source)
+
+ /*
+ redis> SMEMBERS songs
+ 1) "Billie Jean"
+ 2) "Believe Me"
+ */
+ expected2 := []string{"Billie Jean", "Believe Me"}
+ got2_interface, err := redisPoolObj_set.SMembers(source)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+
+ /*
+ redis> SMEMBERS my_songs
+ (empty list or set)
+ */
+ destination := "my_songs"
+ expected3 := []string{}
+ got3_interface, err := redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got3, err := redisPoolObj_set.Strings(got3_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected3, got3) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected3, got3)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, destination)
+
+ /*
+ redis> SMOVE songs my_songs "Believe Me"
+ (integer) 1
+ */
+ value := "Believe Me"
+ expected4 := true
+ got4, err := redisPoolObj_set.SMove(source, destination, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected length %t, but got %t", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS songs
+ 1) "Billie Jean"
+ */
+ expected5 := []string{"Billie Jean"}
+ got5_interface, err := redisPoolObj_set.SMembers(source)
+ if err != nil {
+ t.Fail()
+ }
+ got5, err := redisPoolObj_set.Strings(got5_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected5, got5) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected5, got5)
+ return
+ }
+
+ /*
+ redis> SMEMBERS my_songs
+ 1) "Believe Me"
+ */
+ expected6 := []string{"Believe Me"}
+ got6_interface, err := redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got6, err := redisPoolObj_set.Strings(got6_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected6, got6) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected6, got6)
+ return
+ }
+}
+
+func TestSCard(t *testing.T) {
+ /*
+ redis> SADD tool pc printer phone
+ (integer) 3
+ */
+ key := "tool"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key, "pc", "printer", "phone")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ /*
+ redis> SCARD tool # 非空集合
+ (integer) 3
+ */
+ expected = 3
+ got, err = redisPoolObj_set.SCard(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ /*
+ redis> DEL tool
+ (integer) 1
+ */
+ expected = 1
+ got, err = redisPoolObj_set.Del(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ /*
+ redis> SCARD tool # 空集合
+ (integer) 0
+ */
+ expected = 0
+ got, err = redisPoolObj_set.SCard(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+}
+
+func TestSMembers(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # key 不存在或集合为空
+
+ redis> EXISTS not_exists_key
+ (integer) 0
+ */
+ key := "not_exists_key"
+ expected := false
+ got, err := redisPoolObj_set.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t.", expected, got)
+ return
+ }
+
+ /*
+ redis> SMEMBERS not_exists_key
+ (empty list or set)
+ */
+ expected2 := make([]string, 0)
+ got2_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got2, err := redisPoolObj_set.Strings(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+
+ /*
+ # 非空集合
+
+ redis> SADD language Ruby Python Clojure
+ (integer) 3
+ */
+ key = "language"
+ expected3 := 3
+ got3, err := redisPoolObj_set.SAdd(key, "Clojure", "Python", "Ruby")
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d.", expected3, got3)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SMEMBERS language
+ 1) "Python"
+ 2) "Ruby"
+ 3) "Clojure"
+ */
+ expected4 := []string{"Clojure", "Python", "Ruby"}
+ got4_interface, err := redisPoolObj_set.SMembers(key)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSInter(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ key1 := "group_1"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key1, "LI LEI", "TOM", "JACK")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ key2 := "group_2"
+ expected = 2
+ got, err = redisPoolObj_set.SAdd(key2, "HAN MEIMEI", "JACK")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ /*
+ redis> SMEMBERS group_1
+ 1) "LI LEI"
+ 2) "TOM"
+ 3) "JACK"
+ */
+ expected4 := []string{"LI LEI", "TOM", "JACK"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS group_2
+ 1) "HAN MEIMEI"
+ 2) "JACK"
+ */
+ expected4 = []string{"HAN MEIMEI", "JACK"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SINTER group_1 group_2
+ 1) "JACK"
+ */
+ expected4 = []string{"JACK"}
+ got4_interface, err = redisPoolObj_set.SInter(key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSInterStore(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> SMEMBERS songs
+ 1) "good bye joe"
+ 2) "hello,peter"
+ */
+ key1 := "songs"
+ expected := 2
+ got, err := redisPoolObj_set.SAdd(key1, "good bye joe", "hello,peter")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ expected4 := []string{"good bye joe", "hello,peter"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS my_songs
+ 1) "good bye joe"
+ 2) "falling"
+ */
+ key2 := "my_songs"
+ expected = 2
+ got, err = redisPoolObj_set.SAdd(key2, "good bye joe", "falling")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ expected4 = []string{"good bye joe", "falling"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SINTERSTORE song_interset songs my_songs
+ (integer) 1
+ */
+ destination := "song_interset"
+ expected2 := 1
+ got2, err := redisPoolObj_set.SInterStore(destination, key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d.", expected2, got2)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, destination)
+
+ /*
+ redis> SMEMBERS song_interset
+ 1) "good bye joe"
+ */
+ expected4 = []string{"good bye joe"}
+ got4_interface, err = redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSUnion(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> SMEMBERS songs
+ 1) "Billie Jean"
+ */
+ key1 := "songs"
+ expected := 1
+ got, err := redisPoolObj_set.SAdd(key1, "Billie Jean")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ expected4 := []string{"Billie Jean"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS my_songs
+ 1) "Believe Me"
+ */
+ key2 := "my_songs"
+ expected = 1
+ got, err = redisPoolObj_set.SAdd(key2, "Believe Me")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ expected4 = []string{"Believe Me"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SUNION songs my_songs
+ 1) "Billie Jean"
+ 2) "Believe Me"
+ */
+ expected4 = []string{"Billie Jean", "Believe Me"}
+ got4_interface, err = redisPoolObj_set.SUnion(key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSUnionStore(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> SMEMBERS NoSQL
+ 1) "MongoDB"
+ 2) "Redis"
+ */
+ key1 := "NoSQL"
+ expected := 2
+ got, err := redisPoolObj_set.SAdd(key1, "MongoDB", "Redis")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ expected4 := []string{"MongoDB", "Redis"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS SQL
+ 1) "sqlite"
+ 2) "MySQL"
+ */
+ key2 := "SQL"
+ expected = 2
+ got, err = redisPoolObj_set.SAdd(key2, "sqlite", "MySQL")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ expected4 = []string{"sqlite", "MySQL"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SUNIONSTORE db NoSQL SQL
+ (integer) 4
+ */
+ destination := "db"
+ expected2 := 4
+ got2, err := redisPoolObj_set.SUnionStore(destination, key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d.", expected2, got2)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, destination)
+
+ /*
+ redis> SMEMBERS db
+ 1) "MySQL"
+ 2) "sqlite"
+ 3) "MongoDB"
+ 4) "Redis"
+ */
+ expected4 = []string{"MongoDB", "Redis", "sqlite", "MySQL"}
+ got4_interface, err = redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSDiff(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> SMEMBERS peter's_movies
+ 1) "bet man"
+ 2) "start war"
+ 3) "2012"
+ */
+ key1 := "peter's_movies"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key1, "bet man", "start war", "2012")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ expected4 := []string{"bet man", "start war", "2012"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS joe's_movies
+ 1) "hi, lady"
+ 2) "Fast Five"
+ 3) "2012"
+ */
+ key2 := "joe's_movies"
+ expected = 3
+ got, err = redisPoolObj_set.SAdd(key2, "hi, lady", "Fast Five", "2012")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ expected4 = []string{"hi, lady", "Fast Five", "2012"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SDIFF peter's_movies joe's_movies
+ 1) "bet man"
+ 2) "start war"
+ */
+ expected4 = []string{"bet man", "start war"}
+ got4_interface, err = redisPoolObj_set.SDiff(key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SDIFF joe's_movies peter's_movies
+ 1) "hi, lady"
+ 2) "Fast Five"
+ */
+ expected4 = []string{"hi, lady", "Fast Five"}
+ got4_interface, err = redisPoolObj_set.SDiff(key2, key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
+
+func TestSDiffStore(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> SMEMBERS peter's_movies
+ 1) "bet man"
+ 2) "start war"
+ 3) "2012"
+ */
+ key1 := "peter's_movies"
+ expected := 3
+ got, err := redisPoolObj_set.SAdd(key1, "bet man", "start war", "2012")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key1)
+
+ expected4 := []string{"bet man", "start war", "2012"}
+ got4_interface, err := redisPoolObj_set.SMembers(key1)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err := redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SMEMBERS joe's_movies
+ 1) "hi, lady"
+ 2) "Fast Five"
+ 3) "2012"
+ */
+ key2 := "joe's_movies"
+ expected = 3
+ got, err = redisPoolObj_set.SAdd(key2, "hi, lady", "Fast Five", "2012")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d.", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key2)
+
+ expected4 = []string{"hi, lady", "Fast Five", "2012"}
+ got4_interface, err = redisPoolObj_set.SMembers(key2)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SDIFFSTORE joe_diff_peter joe's_movies peter's_movies
+ (integer) 2
+ */
+ destination := "joe_diff_peter"
+ expected2 := 2
+ got2, err := redisPoolObj_set.SDiffStore(destination, key1, key2)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d.", expected2, got2)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, destination)
+
+ /*
+ redis> SMEMBERS joe_diff_peter
+ 1) "bet man"
+ 2) "start war"
+ */
+ expected4 = []string{"bet man", "start war"}
+ got4_interface, err = redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+
+ /*
+ redis> SDIFFSTORE peter_diff_joe peter's_movies, joe's_movies
+ (integer) 2
+ */
+ destination = "peter_diff_joe"
+ expected2 = 2
+ got2, err = redisPoolObj_set.SDiffStore(destination, key2, key1)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d.", expected2, got2)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, destination)
+
+ /*
+ redis> SMEMBERS joe_diff_peter
+ 1) "hi, lady"
+ 2) "Fast Five"
+ */
+ expected4 = []string{"hi, lady", "Fast Five"}
+ got4_interface, err = redisPoolObj_set.SMembers(destination)
+ if err != nil {
+ t.Fail()
+ }
+ got4, err = redisPoolObj_set.Strings(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected4, got4) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected4, got4)
+ return
+ }
+}
diff --git a/.svn/pristine/25/25b8521c8aada772e1f6465d18604e289c9e5489.svn-base b/.svn/pristine/25/25b8521c8aada772e1f6465d18604e289c9e5489.svn-base
new file mode 100644
index 0000000..bf5a8fb
--- /dev/null
+++ b/.svn/pristine/25/25b8521c8aada772e1f6465d18604e289c9e5489.svn-base
@@ -0,0 +1,378 @@
+/*
+未实现的列表方法:
+BLPOP、BRPOP、BRPOPLPUSH
+*/
+package redisUtil
+
+import (
+ "github.com/gomodule/redigo/redis"
+)
+
+/*
+LPUSH key value [value …]
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+将一个或多个值 value 插入到列表 key 的表头
+
+如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。
+
+如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。
+
+当 key 存在但不是列表类型时,返回一个错误。
+
+Note
+
+在Redis 2.4版本以前的 LPUSH 命令,都只接受单个 value 值。
+
+返回值
+执行 LPUSH 命令后,列表的长度。
+*/
+func (this *RedisPool) LPush(key string, values ...interface{}) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("LPUSH", redis.Args{}.Add(key).AddFlat(values)...))
+ return
+}
+
+/*
+LPUSHX key value
+可用版本: >= 2.2.0
+时间复杂度: O(1)
+将值 value 插入到列表 key 的表头,当且仅当 key 存在并且是一个列表。
+
+和 LPUSH key value [value …] 命令相反,当 key 不存在时, LPUSHX 命令什么也不做。
+
+返回值
+LPUSHX 命令执行之后,表的长度。
+*/
+func (this *RedisPool) LPushX(key string, values ...interface{}) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("LPUSHX", redis.Args{}.Add(key).AddFlat(values)...))
+ return
+}
+
+/*
+RPUSH key value [value …]
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+将一个或多个值 value 插入到列表 key 的表尾(最右边)。
+
+如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。
+
+如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。
+
+当 key 存在但不是列表类型时,返回一个错误。
+
+Note
+
+在 Redis 2.4 版本以前的 RPUSH 命令,都只接受单个 value 值。
+
+返回值
+执行 RPUSH 操作后,表的长度。
+*/
+func (this *RedisPool) RPush(key string, values ...interface{}) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("RPUSH", redis.Args{}.Add(key).AddFlat(values)...))
+ return
+}
+
+/*
+RPUSHX key value
+可用版本: >= 2.2.0
+时间复杂度: O(1)
+将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。
+
+和 RPUSH key value [value …] 命令相反,当 key 不存在时, RPUSHX 命令什么也不做。
+
+返回值
+RPUSHX 命令执行之后,表的长度。
+*/
+func (this *RedisPool) RPushX(key string, values ...interface{}) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("RPUSHX", redis.Args{}.Add(key).AddFlat(values)...))
+ return
+}
+
+/*
+LPOP key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+移除并返回列表 key 的头元素。
+
+返回值
+列表的头元素。 当 key 不存在时,返回 nil 。
+*/
+func (this *RedisPool) LPop(key string) (item interface{}, exist bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ item, err = conn.Do("LPOP", key)
+ if err != nil {
+ return
+ }
+ if item == nil {
+ return
+ }
+
+ exist = true
+
+ return
+}
+
+/*
+RPOP key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+移除并返回列表 key 的尾元素。
+
+返回值
+列表的尾元素。 当 key 不存在时,返回 nil 。
+*/
+func (this *RedisPool) RPop(key string) (item interface{}, exist bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ item, err = conn.Do("RPOP", key)
+ if err != nil {
+ return
+ }
+ if item == nil {
+ return
+ }
+
+ exist = true
+
+ return
+}
+
+/*
+RPOPLPUSH source destination
+可用版本: >= 1.2.0
+时间复杂度: O(1)
+命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:
+
+将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
+
+将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。
+
+举个例子,你有两个列表 source 和 destination , source 列表有元素 a, b, c , destination 列表有元素 x, y, z ,执行 RPOPLPUSH source destination 之后, source 列表包含元素 a, b , destination 列表包含元素 c, x, y, z ,并且元素 c 会被返回给客户端。
+
+如果 source 不存在,值 nil 被返回,并且不执行其他动作。
+
+如果 source 和 destination 相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。
+
+返回值
+被弹出的元素。
+*/
+func (this *RedisPool) RPopLPush(source, destination string) (item interface{}, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ item, err = conn.Do("RPOPLPUSH", source, destination)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+/*
+LREM key count value
+可用版本: >= 1.0.0
+时间复杂度: O(N), N 为列表的长度。
+根据参数 count 的值,移除列表中与参数 value 相等的元素。
+
+count 的值可以是以下几种:
+
+count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
+
+count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
+
+count = 0 : 移除表中所有与 value 相等的值。
+
+返回值
+被移除元素的数量。 因为不存在的 key 被视作空表(empty list),所以当 key 不存在时, LREM 命令总是返回 0 。
+*/
+// 错误对象
+func (this *RedisPool) LRem(key string, count int, value string) (removeCount int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ removeCount, err = redis.Int(conn.Do("LREM", key, count, value))
+ return
+}
+
+/*
+LLEN key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+返回列表 key 的长度。
+
+如果 key 不存在,则 key 被解释为一个空列表,返回 0 .
+
+如果 key 不是列表类型,返回一个错误。
+
+返回值
+列表 key 的长度。
+*/
+func (this *RedisPool) LLen(key string) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("LLEN", key))
+ return
+}
+
+/*
+LINDEX key index
+可用版本: >= 1.0.0
+时间复杂度:O(N), N 为到达下标 index 过程中经过的元素数量。因此,对列表的头元素和尾元素执行 LINDEX 命令,复杂度为O(1)。
+返回列表 key 中,下标为 index 的元素。
+
+下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
+
+你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
+
+如果 key 不是列表类型,返回一个错误。
+
+返回值
+列表中下标为 index 的元素。 如果 index 参数的值不在列表的区间范围内(out of range),返回 nil 。
+*/
+func (this *RedisPool) LIndex(key string, index int) (item interface{}, exist bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ item, err = conn.Do("LINDEX", key, index)
+ if err != nil {
+ return
+ }
+ if item == nil {
+ return
+ }
+
+ exist = true
+ return
+}
+
+/*
+LINSERT key BEFORE|AFTER pivot value
+可用版本: >= 2.2.0
+时间复杂度: O(N), N 为寻找 pivot 过程中经过的元素数量。
+将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
+
+当 pivot 不存在于列表 key 时,不执行任何操作。
+
+当 key 不存在时, key 被视为空列表,不执行任何操作。
+
+如果 key 不是列表类型,返回一个错误。
+
+返回值
+如果命令执行成功,返回插入操作完成之后,列表的长度。 如果没有找到 pivot ,返回 -1 。 如果 key 不存在或为空列表,返回 0 。
+*/
+func (this *RedisPool) LInsert(key, beforeOrAfter string, pivot, value interface{}) (length int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ length, err = redis.Int(conn.Do("LINSERT", key, beforeOrAfter, pivot, value))
+ return
+}
+
+/*
+LSET key index value
+可用版本: >= 1.0.0
+时间复杂度:对头元素或尾元素进行 LSET 操作,复杂度为 O(1)。其他情况下,为 O(N), N 为列表的长度。
+将列表 key 下标为 index 的元素的值设置为 value 。
+
+当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。
+
+关于列表下标的更多信息,请参考 LINDEX key index 命令。
+
+返回值
+操作成功返回 ok ,否则返回错误信息。
+*/
+func (this *RedisPool) LSet(key string, index int, value interface{}) (err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ _, err = conn.Do("LSet", key, index, value)
+ return
+}
+
+/*
+LRANGE key start stop
+可用版本: >= 1.0.0
+时间复杂度: O(S+N), S 为偏移量 start , N 为指定区间内元素的数量。
+返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。
+
+下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
+
+你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
+
+注意LRANGE命令和编程语言区间函数的区别
+假如你有一个包含一百个元素的列表,对该列表执行 LRANGE list 0 10 ,结果是一个包含11个元素的列表,这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的 Range.new 、 Array#slice 和Python的 range() 函数。
+
+超出范围的下标
+超出范围的下标值不会引起错误。
+
+如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,那么 LRANGE 返回一个空列表。
+
+如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。
+
+返回值
+一个列表,包含指定区间内的元素。
+*/
+func (this *RedisPool) LRange(key string, start, stop int) (reply interface{}, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ reply, err = conn.Do("LRANGE", key, start, stop)
+ return
+}
+
+/*
+LTRIM key start stop
+可用版本: >= 1.0.0
+时间复杂度: O(N), N 为被移除的元素的数量。
+对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
+
+举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。
+
+下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
+
+你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
+
+当 key 不是列表类型时,返回一个错误。
+
+LTRIM 命令通常和 LPUSH key value [value …] 命令或 RPUSH key value [value …] 命令配合使用,举个例子:
+
+LPUSH log newest_log
+LTRIM log 0 99
+这个例子模拟了一个日志程序,每次将最新日志 newest_log 放到 log 列表中,并且只保留最新的 100 项。注意当这样使用 LTRIM 命令时,时间复杂度是O(1),因为平均情况下,每次只有一个元素被移除。
+
+注意LTRIM命令和编程语言区间函数的区别
+假如你有一个包含一百个元素的列表 list ,对该列表执行 LTRIM list 0 10 ,结果是一个包含11个元素的列表,这表明 stop 下标也在 LTRIM 命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的 Range.new 、 Array#slice 和Python的 range() 函数。
+
+超出范围的下标
+超出范围的下标值不会引起错误。
+
+如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,或者 start > stop , LTRIM 返回一个空列表(因为 LTRIM 已经将整个列表清空)。
+
+如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。
+
+返回值
+命令执行成功时,返回 ok 。
+*/
+func (this *RedisPool) LTrim(key string, start, stop int) (err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ _, err = conn.Do("LTRIM", key, start, stop)
+ return
+}
diff --git a/.svn/pristine/25/25fe816e9e9fd164ec610c7921a8639c1dcbfb15.svn-base b/.svn/pristine/25/25fe816e9e9fd164ec610c7921a8639c1dcbfb15.svn-base
new file mode 100644
index 0000000..c469ac4
--- /dev/null
+++ b/.svn/pristine/25/25fe816e9e9fd164ec610c7921a8639c1dcbfb15.svn-base
@@ -0,0 +1,131 @@
+package gameServerMgr
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ . "Framework/managecenterModel"
+ "goutil/logUtil"
+ "goutil/securityUtil"
+ "goutil/webUtil"
+)
+
+// 登陆助手类
+type LoginUtil struct{}
+
+// 验证登陆信息
+// partnerId:合作商Id
+// userId:合作商用户Id
+// loginInfo:登陆信息
+// isIntranet:是否是内网:true,内网;false:外网
+// 返回值:
+// 成功与否
+// 错误对象
+func (this *LoginUtil) CheckLoginInfo(partnerId int32, userId, loginInfo string, isIntranet bool) (success bool, err error) {
+ // 验证用户合法性
+ loginItemList := strings.Split(loginInfo, "_")
+ if len(loginItemList) != 2 {
+ err = fmt.Errorf("CheckLoginInfo Failed. partnerId:%d, userId:%s, loginInfo:%s", partnerId, userId, loginInfo)
+ return
+ }
+
+ //将requestUrl地址进行拆分
+ requestDomainList := strings.Split(loginItemList[1], ";")
+
+ //请求的主域名
+ requestDomain := ""
+ if isIntranet || len(requestDomainList) == 1 {
+ requestDomain = requestDomainList[0]
+ } else {
+ requestDomain = requestDomainList[1]
+ }
+
+ //构造请求url
+ requestUrl := fmt.Sprintf("http://%s/API/CheckDynamicLoginKey.ashx", requestDomain)
+
+ // 定义请求参数
+ postDict := make(map[string]string)
+ postDict["UserId"] = userId
+ postDict["LoginKey"] = loginItemList[0]
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err1 := webUtil.PostMapData(requestUrl, postDict, header, transport)
+ if err1 != nil {
+ err = fmt.Errorf("CheckLoginInfo Failed. partnerId:%d, userId:%s, loginInfo:%s, err:%s", partnerId, userId, loginInfo, err1)
+ return
+ }
+ if statusCode != 200 {
+ err = fmt.Errorf("CheckLoginInfo Failed. partnerId:%d, userId:%s, loginInfo:%s, statusCode:%d", partnerId, userId, loginInfo, statusCode)
+ return
+ }
+
+ // 解析返回值
+ returnObj := new(ReturnObject)
+ if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
+ err = fmt.Errorf("CheckLoginInfo Failed. partnerId:%d, userId:%s, loginInfo:%s, err:%s", partnerId, userId, loginInfo, err)
+ return
+ }
+
+ // 判断返回状态是否为成功
+ if returnObj.Code != 0 {
+ logUtil.ErrorLog(fmt.Sprintf("CheckLoginInfo Failed. partnerId:%d, userId:%s, loginInfo:%s, Code:%d, Message:%s", partnerId, userId, loginInfo, returnObj.Code, returnObj.Message))
+ return
+ }
+
+ success = true
+
+ return
+}
+
+// 本地验证登陆信息
+// partnerId:合作商Id
+// userId:合作商用户Id
+// loginInfo:登陆信息
+// 返回值:
+// 成功与否
+// 错误对象
+func CheckDynamicTokenLocal(partnerId int32, userId, loginInfo string) (success bool, err error) {
+ //1001直接返回true
+ if partnerId == 1001 {
+ return true, nil
+ }
+
+ //非1001渠道验证
+ if len(loginInfo) == 0 {
+ success = false
+ err = fmt.Errorf("Err:%s", "LoginInfo is null!")
+ return
+ }
+ // 验证用户合法性
+ loginItemList := strings.Split(loginInfo, "_")
+ if len(loginItemList) != 2 {
+ success = false
+ err = fmt.Errorf("CheckLoginInfo Failed. userId:%s, loginInfo:%s", userId, loginInfo)
+ return
+ }
+
+ //生成key
+ localSign := securityUtil.Md5String(userId+GetSysConfig().DynamicLoginKey+loginItemList[1], true)
+
+ //判断签名是佛正确
+ if localSign != loginItemList[0] {
+ success = false
+ err = fmt.Errorf("CheckLoginInfo Failed. Sign Check Failed! userId:%s,LocalSign:%s,loginInfo:%s", userId, localSign, loginInfo)
+ return
+ }
+
+ success = true
+ return
+}
+
+// ------------------类型定义和业务逻辑的分隔符-------------------------
+
+var (
+ LoginUtilObj = new(LoginUtil)
+)
diff --git a/.svn/pristine/26/26022c8a11741f20169313a7438cfe711b0ee295.svn-base b/.svn/pristine/26/26022c8a11741f20169313a7438cfe711b0ee295.svn-base
new file mode 100644
index 0000000..d5f7c76
--- /dev/null
+++ b/.svn/pristine/26/26022c8a11741f20169313a7438cfe711b0ee295.svn-base
@@ -0,0 +1,112 @@
+package webServer
+
+import (
+ "net/http"
+
+ "common/resultStatus"
+)
+
+// 处理函数
+type HandleFunc func(context *ApiContext) *ResponseObject
+
+// ApiHandler
+//
+// @description: API处理结构
+type ApiHandler struct {
+ // API完整路径名称
+ apiFullName string
+
+ // 方法定义
+ handleFun HandleFunc
+
+ // 方法参数名称集合
+ funcParamNames []string
+}
+
+// ApiFullName
+//
+// @description: API完整路径名称
+//
+// parameter:
+//
+// @receiver this: this
+//
+// return:
+//
+// @string:
+func (this *ApiHandler) ApiFullName() string {
+ return this.apiFullName
+}
+
+// HandleFun
+//
+// @description: 方法定义
+//
+// parameter:
+//
+// @receiver this: this
+//
+// return:
+//
+// @HandleFunc: 方法
+func (this *ApiHandler) HandleFun() HandleFunc {
+ return this.handleFun
+}
+
+// FuncParamNames
+//
+// @description: 方法参数名称集合
+//
+// parameter:
+//
+// @receiver this: this
+//
+// return:
+//
+// @[]string: 方法参数名称集合
+func (this *ApiHandler) FuncParamNames() []string {
+ return this.funcParamNames
+}
+
+// CheckParam
+//
+// @description: 检测参数数量
+//
+// parameter:
+//
+// @receiver this: this
+// @r:
+//
+// return:
+//
+// @resultStatus.ResultStatus: 状态码数据
+func (this *ApiHandler) CheckParam(r *http.Request) resultStatus.ResultStatus {
+ for _, name := range this.funcParamNames {
+ if r.Form[name] == nil || len(r.Form[name]) == 0 {
+ return resultStatus.APIParamError
+ }
+ }
+
+ return resultStatus.Success
+}
+
+// newApiHandler
+//
+// @description: 创建新的请求方法对象
+//
+// parameter:
+//
+// @_apiFullName: API完整路径名称
+// @_funcDefinition: 方法定义
+// @_funcParamNames: 方法参数名称集合
+//
+// return:
+//
+// @*ApiHandler: 请求方法对象
+func newApiHandler(_apiFullName string, _funcDefinition HandleFunc, _funcParamNames ...string) *ApiHandler {
+ return &ApiHandler{
+ apiFullName: _apiFullName,
+ handleFun: _funcDefinition,
+ funcParamNames: _funcParamNames,
+ }
+}
diff --git a/.svn/pristine/26/2621e7b98a6ac756be9f2d95dd9e284ddb2338b4.svn-base b/.svn/pristine/26/2621e7b98a6ac756be9f2d95dd9e284ddb2338b4.svn-base
new file mode 100644
index 0000000..7604d4a
--- /dev/null
+++ b/.svn/pristine/26/2621e7b98a6ac756be9f2d95dd9e284ddb2338b4.svn-base
@@ -0,0 +1,17 @@
+module Framework
+
+go 1.22.2
+
+replace goutil => ../goutil
+
+require (
+ github.com/Shopify/sarama v1.29.1
+ github.com/go-sql-driver/mysql v1.5.0
+ github.com/gorilla/websocket v1.4.2
+ github.com/jinzhu/gorm v1.9.12
+ github.com/rabbitmq/amqp091-go v1.8.1
+ github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414
+ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.230
+ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vms v1.0.230
+ goutil v0.0.0-00010101000000-000000000000
+)
diff --git a/.svn/pristine/26/262ac8472b6314d517f3a9c48c61c54f3b4d315d.svn-base b/.svn/pristine/26/262ac8472b6314d517f3a9c48c61c54f3b4d315d.svn-base
new file mode 100644
index 0000000..5079912
--- /dev/null
+++ b/.svn/pristine/26/262ac8472b6314d517f3a9c48c61c54f3b4d315d.svn-base
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.svn/pristine/26/264f287a04ade2aafd862fcba87d65aa33d2dfa4.svn-base b/.svn/pristine/26/264f287a04ade2aafd862fcba87d65aa33d2dfa4.svn-base
new file mode 100644
index 0000000..afc3ba7
--- /dev/null
+++ b/.svn/pristine/26/264f287a04ade2aafd862fcba87d65aa33d2dfa4.svn-base
@@ -0,0 +1,130 @@
+package notify_util
+
+import (
+ "fmt"
+
+ "Framework/goroutineMgr"
+ "goutil/logUtil"
+ "goutil/syncUtil"
+)
+
+const (
+ deathLockTime = 0
+)
+
+// notifyCenter
+// @description: 玩家信息务逻辑类
+type notifyCenter struct {
+ // key:初始化成功的标志名称 val:占位符
+ registerMap map[string]func()
+ mutex *syncUtil.RWLocker
+}
+
+// newNotifyCenter
+// @description: 构造对象
+// parameter:
+// return:
+// @*notifyCenter:
+func newNotifyCenter() *notifyCenter {
+ return ¬ifyCenter{
+ registerMap: make(map[string]func()),
+ mutex: syncUtil.NewRWLocker(),
+ }
+}
+
+// register
+// @description: 注册需要被通知的对象
+// parameter:
+// @receiver nc:
+// @chanName:唯一标识
+// @cf:回调方法
+// return:
+func (nc *notifyCenter) register(chanName string, cf func()) {
+ if isOk, prevStack, currStack := nc.mutex.Lock(deathLockTime); isOk == false {
+ //记日志
+ errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s \n当前堆栈:\n%s", prevStack, currStack)
+ panic(errMsg)
+ }
+ defer nc.mutex.Unlock()
+ if _, exists := nc.registerMap[chanName]; exists {
+ panic(fmt.Errorf("registerMap.Register-%s已经存在,请检查", chanName))
+ }
+
+ nc.registerMap[chanName] = cf
+}
+
+// @description: 取消启动成功通知注册
+// parameter:
+// @receiver nc:
+// @name:唯一标识
+// return:
+func (nc *notifyCenter) unregister(name string) {
+ if isOk, prevStack, currStack := nc.mutex.Lock(deathLockTime); isOk == false {
+ //记日志
+ errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s \n当前堆栈:\n%s", prevStack, currStack)
+ panic(errMsg)
+ }
+ defer nc.mutex.Unlock()
+
+ delete(nc.registerMap, name)
+}
+
+// notify
+// @description: 通知所有已注册的对象
+// parameter:
+// @receiver nc:
+// return:
+func (nc *notifyCenter) notify() {
+ // 处理goroutine数量
+ goroutineName := "notifyCenter.Notify"
+ goroutineMgr.MonitorZero(goroutineName)
+ defer goroutineMgr.ReleaseMonitor(goroutineName)
+
+ if isOk, prevStack, currStack := nc.mutex.RLock(deathLockTime); isOk == false {
+ //记日志
+ errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s \n当前堆栈:\n%s", prevStack, currStack)
+ panic(errMsg)
+ }
+ defer nc.mutex.RUnlock()
+
+ for name, cf := range nc.registerMap {
+ cf()
+ msg := fmt.Sprintf("通知:%s初始化成功", name)
+ logUtil.DebugLog(msg)
+ }
+}
+
+// notify2
+// @description: 通知所有已注册的对象,该方法会在捕获第一个err的时候停止后续的通知。多用于系统启动的判定
+// parameter:
+// @receiver nc:
+// return:
+// @error:
+func (nc *notifyCenter) notify2() (err error) {
+ // 处理goroutine数量
+ goroutineName := "notifyCenter.Notify"
+ goroutineMgr.MonitorZero(goroutineName)
+ defer goroutineMgr.ReleaseMonitor(goroutineName)
+
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("notify2 err:%s", r)
+ logUtil.ErrorLog(err.Error())
+ }
+ }()
+
+ if isOk, prevStack, currStack := nc.mutex.RLock(deathLockTime); isOk == false {
+ //记日志
+ errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s \n当前堆栈:\n%s", prevStack, currStack)
+ panic(errMsg)
+ }
+ defer nc.mutex.RUnlock()
+
+ for name, cf := range nc.registerMap {
+ cf()
+ msg := fmt.Sprintf("通知:%s初始化成功", name)
+ logUtil.DebugLog(msg)
+ }
+
+ return
+}
diff --git a/.svn/pristine/26/26fd4cb975dbbbc57bf60a2d6c23dd8242dce9b2.svn-base b/.svn/pristine/26/26fd4cb975dbbbc57bf60a2d6c23dd8242dce9b2.svn-base
new file mode 100644
index 0000000..f264a26
--- /dev/null
+++ b/.svn/pristine/26/26fd4cb975dbbbc57bf60a2d6c23dd8242dce9b2.svn-base
@@ -0,0 +1,57 @@
+package timeUtil
+
+import (
+ "testing"
+ "time"
+)
+
+func TestConverToStandardFormat(t *testing.T) {
+ str := "2018-10-10T10:10:10"
+ expected := time.Date(2018, 10, 10, 10, 10, 10, 0, time.Local)
+
+ got, err := ConverToStandardFormat(str)
+ if err != nil {
+ t.Errorf("发生错误,错误信息为:%s", err)
+ }
+
+ if got != expected {
+ t.Errorf("转换不正确,期待:%s, 实际:%s", expected, got)
+ }
+}
+
+func TestConvertToInt(t *testing.T) {
+ date := time.Date(2018, 10, 10, 10, 10, 10, 0, time.Local)
+ finalInt := ConvertToInt(date)
+ expecteInt := 20181010
+
+ if finalInt != expecteInt {
+ t.Errorf("转换不正确,期待:%d, 实际:%d", expecteInt, finalInt)
+ }
+}
+
+func TestSubDay(t *testing.T) {
+ time1 := time.Now().AddDate(0, 0, 5)
+ time2 := time.Now()
+ expected := 5
+
+ got := SubDay(time1, time2)
+ if got != expected {
+ t.Errorf("Expected %d, but now got %d.", expected, got)
+ }
+}
+
+func TestParseTimeString(t *testing.T) {
+ val := "12:13:14"
+ expectedHour := 12
+ expectedMinute := 13
+ expectedSecond := 14
+
+ err, hour, miniute, second := ParseTimeString(val)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if expectedHour != hour || expectedMinute != miniute || expectedSecond != second {
+ t.Fail()
+ }
+}
diff --git a/.svn/pristine/28/281351a336934c29f0bf81f0e3cfb3ba03e237b0.svn-base b/.svn/pristine/28/281351a336934c29f0bf81f0e3cfb3ba03e237b0.svn-base
new file mode 100644
index 0000000..b835d9e
--- /dev/null
+++ b/.svn/pristine/28/281351a336934c29f0bf81f0e3cfb3ba03e237b0.svn-base
@@ -0,0 +1,6 @@
+package internal
+
+import (
+ _ "logincenter/internal/game"
+ _ "logincenter/internal/user"
+)
diff --git a/.svn/pristine/28/2872d3f11847c786465856bc05af9651a484188c.svn-base b/.svn/pristine/28/2872d3f11847c786465856bc05af9651a484188c.svn-base
new file mode 100644
index 0000000..ebc34cb
--- /dev/null
+++ b/.svn/pristine/28/2872d3f11847c786465856bc05af9651a484188c.svn-base
@@ -0,0 +1,71 @@
+package websocketUtil
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+var (
+ wsmap sync.Map
+ errLog func(format string, args ...interface{})
+ debugLog func(format string, args ...interface{})
+)
+
+// SetLog
+// @Description:设置日志回调函数信息
+// @param errLogFun 错误日志回调函数
+// @param debugLogFun debug日志回调函数
+func SetLog(errLogFun, debugLogFun func(format string, args ...interface{})) {
+ errLog = errLogFun
+ debugLog = debugLogFun
+}
+
+// Send
+// @Description: 发送数据
+// @param wsurl 发送地址
+// @param st 发送类型,使用websocket下的定义
+// @param data 发送数据
+// @return error
+func Send(wsurl string, st int, data []byte) error {
+ if debugLog == nil || errLog == nil {
+ return errors.New("websocketUtil未设置errLog,debugLog回调函数,请调用websocketUtil.Setlog函数设置相关信息")
+ }
+
+ m, err := getOrAdd(wsurl)
+ if err != nil {
+ errLog(fmt.Sprintf("websocketUtil.Send error:%s", err))
+ return err
+ }
+
+ m.send(st, data)
+
+ return nil
+}
+
+// getOrAdd
+// @Description:获取或者添加对象
+// @param url string
+// @return *model
+// @return error
+func getOrAdd(url string) (*model, error) {
+ var m *model
+ var err error
+
+ v, isOk := wsmap.Load(url)
+ if isOk {
+ m = v.(*model)
+ return m, nil
+ }
+
+ // 不存在,创建对应的socket连接
+ m, err = newModel(url)
+ if err != nil {
+ return nil, err
+ }
+
+ // 保存到map
+ wsmap.Store(url, m)
+
+ return m, err
+}
diff --git a/.svn/pristine/28/28f055a2b9e8a852f03d50095156e421917e10b3.svn-base b/.svn/pristine/28/28f055a2b9e8a852f03d50095156e421917e10b3.svn-base
new file mode 100644
index 0000000..d3ae5d2
--- /dev/null
+++ b/.svn/pristine/28/28f055a2b9e8a852f03d50095156e421917e10b3.svn-base
@@ -0,0 +1,75 @@
+package goroutineMgr
+
+import (
+ "fmt"
+ "runtime"
+ "sync"
+
+ "framework/monitorNewMgr"
+ "goutil/logUtil"
+)
+
+var (
+ goroutineInfoMap map[string]int = make(map[string]int)
+ goroutineInfoMutex sync.RWMutex
+ goroutineWarnCount int = 50
+)
+
+func init() {
+ monitorNewMgr.RegisterMonitorFunc(monitor)
+}
+
+// 设置系统协程上报阈值
+func SetGoroutineWarnCount(warnCount int) {
+ goroutineWarnCount = warnCount
+}
+
+func registerGoroutineInfo(goroutineName string, count int) {
+ goroutineInfoMutex.Lock()
+ defer goroutineInfoMutex.Unlock()
+
+ goroutineInfoMap[goroutineName] = count
+}
+
+// 监控指定的goroutine
+func Monitor(goroutineName string) {
+ increaseCount(goroutineName)
+ registerGoroutineInfo(goroutineName, 1)
+}
+
+// 只添加数量,不监控
+func MonitorZero(goroutineName string) {
+ increaseCount(goroutineName)
+}
+
+// 释放监控
+func ReleaseMonitor(goroutineName string) {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+ }
+
+ decreaseCount(goroutineName)
+}
+
+func monitor() error {
+ // 判断当前goroutine数量是否达到打印条件(数量查过设置的值就打印)
+ if goroutineWarnCount >= runtime.NumGoroutine() {
+ return nil
+ }
+ /*
+ 先记录活跃的goroutine的数量信息
+ 然后再判断数量是否匹配
+ */
+ logGoroutineCountInfo()
+
+ goroutineInfoMutex.RLock()
+ defer goroutineInfoMutex.RUnlock()
+
+ for goroutineName, expectedCount := range goroutineInfoMap {
+ if currCount := getGoroutineCount(goroutineName); currCount != expectedCount {
+ return fmt.Errorf("%s需要%d个goroutine,现在有%d个", goroutineName, expectedCount, currCount)
+ }
+ }
+
+ return nil
+}
diff --git a/.svn/pristine/2a/2a4adce6fe53177181f083b4ac4b0cd9fba5b1fe.svn-base b/.svn/pristine/2a/2a4adce6fe53177181f083b4ac4b0cd9fba5b1fe.svn-base
new file mode 100644
index 0000000..eb3d5c4
--- /dev/null
+++ b/.svn/pristine/2a/2a4adce6fe53177181f083b4ac4b0cd9fba5b1fe.svn-base
@@ -0,0 +1,18 @@
+package monitorNewMgr
+
+//历史监控信息
+type MonitorHistory struct {
+ //监控信息
+ MonitorMessage string
+
+ //时间戳
+ Timestamp int64
+}
+
+//new一个监控历史信息
+func newMonitorHistory(monitorMessage string, timestamp int64) *MonitorHistory {
+ return &MonitorHistory{
+ MonitorMessage: monitorMessage,
+ Timestamp: timestamp,
+ }
+}
diff --git a/.svn/pristine/2a/2a53f94905747f4fa5f73ac48126d3788f20ea2b.svn-base b/.svn/pristine/2a/2a53f94905747f4fa5f73ac48126d3788f20ea2b.svn-base
new file mode 100644
index 0000000..5977d2a
--- /dev/null
+++ b/.svn/pristine/2a/2a53f94905747f4fa5f73ac48126d3788f20ea2b.svn-base
@@ -0,0 +1,343 @@
+package rank_util
+
+import (
+ "sync"
+)
+
+// RankUtil
+// @description:排行工具类
+type RankUtil struct {
+ // maxCount 排行榜最大数量
+ maxCount int
+
+ // compar 对比函数 返回含义 -1:ab
+ compar func(a, b interface{}) int
+
+ // dataList 排行数据
+ dataList []*Model
+
+ // dataDict 数据字典
+ dataDict map[string]*Model
+
+ // dataLock 数据锁
+ dataLock sync.RWMutex
+}
+
+// NewRankUtil
+// @description: 构造排行对象
+// parameter:
+// @mc:最大容量
+// @comp:元素比对方法
+// return:
+func NewRankUtil(mc int, comp func(a, b interface{}) int) *RankUtil {
+ result := &RankUtil{
+ maxCount: mc,
+ compar: comp,
+ dataList: make([]*Model, 0, mc),
+ dataDict: make(map[string]*Model, mc),
+ }
+
+ return result
+}
+
+// GetMaxCount
+// @description: 获取排行榜最大数量
+// parameter:
+// @receiver r:
+// return:
+// @int:
+func (r *RankUtil) GetMaxCount() int {
+ return r.maxCount
+}
+
+// GetCount
+// @description: 获取排行榜当前数量
+// parameter:
+// @receiver r:
+// return:
+// @int:
+func (r *RankUtil) GetCount() int {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ return len(r.dataList)
+}
+
+// IsFull
+// @description: 判断排行榜是否已经满了
+// parameter:
+// @receiver r:
+// return:
+// @bool:
+func (r *RankUtil) IsFull() bool {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ return len(r.dataList) == r.maxCount
+}
+
+// GetAll
+// @description: 获取排行榜内容
+// parameter:
+// @receiver r:
+// return:
+// @[]*Model:
+func (r *RankUtil) GetAll() []*Model {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ result := make([]*Model, 0, len(r.dataList))
+ for _, item := range r.dataList {
+ if item == nil || item.obj == nil {
+ break
+ }
+
+ result = append(result, item)
+ }
+
+ return result
+}
+
+// GetRankListBySkip
+// @description: 获取排行榜内容
+// parameter:
+// @receiver r:
+// @skip:跳过的数量
+// @count:跳过后需要返回的数量
+// return:
+// @[]*Model:
+func (r *RankUtil) GetRankListBySkip(skip, count int) []*Model {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ result := make([]*Model, 0, count)
+ cn := len(r.dataList)
+ if skip >= cn {
+ return result
+ }
+
+ for i := 0; i < count; i++ {
+ item := r.dataList[skip+i]
+ if item == nil || item.obj == nil {
+ break
+ }
+
+ result = append(result, item)
+ }
+
+ return result
+}
+
+// GetItemForK
+// @description: 根据key获取对象
+// parameter:
+// @receiver r:
+// @k:key
+// return:
+// @*Model:
+func (r *RankUtil) GetItemForK(k string) *Model {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ item, _ := r.dataDict[k]
+
+ return item
+}
+
+// GetItemForRank
+// @description: 根据排名获取对应对象
+// parameter:
+// @receiver r:
+// @rank:排名
+// return:
+// @*Model:
+func (r *RankUtil) GetItemForRank(rank int) *Model {
+ r.dataLock.RLock()
+ defer r.dataLock.RUnlock()
+
+ if len(r.dataList) < rank {
+ return nil
+ }
+
+ return r.dataList[rank-1]
+}
+
+// Refresh
+// @description: 刷新排行榜
+// parameter:
+// @receiver r:
+// @k:key
+// @o:排行持有的对象,业务层不应该持有该对象。否则业务层更改内容,会导致排行榜内容被改变
+// @isup:变动是否升高
+// return:
+// @changeRank:排行是否变动
+// @dm:如果有对象,因为排行变动导致掉出排行榜,则返回该对象,否则返回nil
+func (r *RankUtil) Refresh(k string, o interface{}, isup bool) (changeRank bool, dm *Model) {
+ r.dataLock.Lock()
+ defer r.dataLock.Unlock()
+
+ changeRank = false
+ curItem, exists := r.dataDict[k]
+ if isup {
+ if !exists {
+ newRank := len(r.dataList) + 1
+ curItem = &Model{rank: newRank, key: k, obj: o}
+ // 排行榜未满,必定入榜,则先加入排行榜
+ if newRank <= r.maxCount {
+ r.dataList = append(r.dataList, curItem)
+ r.dataDict[curItem.key] = curItem
+ changeRank = true
+ _, dm = r.upRank(curItem)
+ } else {
+ changeRank, dm = r.upRank(curItem)
+ }
+ } else {
+ curItem.obj = o
+ changeRank, dm = r.upRank(curItem)
+ }
+ } else {
+ // 如果在排行榜内,从之前往下比较
+ if exists {
+ curItem.obj = o
+ changeRank = r.downRank(curItem)
+ } else {
+ // 如果不在排行榜内,直接结束
+ }
+ }
+
+ return
+}
+
+// Delete
+// @description: 删除k指定的对象,很耗性能,不建议高频使用
+// parameter:
+// @receiver r:
+// @k:key
+// return:
+// @bool:true:代表key存在排行榜中,并且删除成功 false:其他情况
+func (r *RankUtil) Delete(k string) bool {
+ r.dataLock.Lock()
+ defer r.dataLock.Unlock()
+
+ m, exists := r.dataDict[k]
+ if !exists {
+ return false
+ }
+
+ //从当前位置向后移动,到最后的时候,删除
+ for {
+ if m.rank >= len(r.dataList) {
+ break
+ }
+
+ am := r.dataList[m.rank]
+ r.exchange(m, am)
+ m = am
+ }
+
+ //最后一个应该是要删除的对象
+ r.dataList = append(r.dataList[:m.rank-1:r.maxCount], r.dataList[m.rank:]...)
+ delete(r.dataDict, k)
+
+ return true
+}
+
+// upRank
+// @description: 排行升高
+// parameter:
+// @receiver r:
+// @curItem:当前对象
+// return:
+// @changeRank:排行是否变动
+// @dm:因排行变动被移除排行的对象
+func (r *RankUtil) upRank(curItem *Model) (changeRank bool, dm *Model) {
+ changeRank = false
+ for {
+ // rank=1,排在第一位,下标为0,故这里需要-2为上一位的下标
+ beforeIndex := curItem.rank - 2
+ if beforeIndex < 0 {
+ break
+ }
+
+ beforeItem := r.dataList[beforeIndex]
+ if r.compar(curItem.obj, beforeItem.obj) <= 0 {
+ break
+ }
+
+ // 交换操作
+ tdm := r.exchange(curItem, beforeItem)
+ if tdm != nil {
+ dm = tdm
+ }
+
+ curItem = beforeItem
+ changeRank = true
+ }
+
+ return
+}
+
+// downRank
+// @description: 排行降低
+// parameter:
+// @receiver r:
+// @curItem:当前对象
+// return:
+// @bool:
+func (r *RankUtil) downRank(curItem *Model) bool {
+ changeRank := false
+
+ for {
+ // rank=1,排在第一位,下标为0,需要对比rank=2的,下标为1,故这里直接取rank即可
+ afterIndex := curItem.rank
+ if afterIndex >= len(r.dataList) {
+ break
+ }
+
+ afterItem := r.dataList[afterIndex]
+ if r.compar(afterItem.obj, curItem.obj) <= 0 {
+ break
+ }
+
+ // 交换操作
+ r.exchange(curItem, afterItem)
+
+ curItem = afterItem
+ changeRank = true
+ }
+
+ return changeRank
+}
+
+// exchange
+// @description: 排行对象交换
+// parameter:
+// @receiver r:
+// @a:对象a
+// @b:对象b
+// return:
+// @delRank:因交换被移除排行榜的对象
+func (r *RankUtil) exchange(a, b *Model) (dm *Model) {
+ tempObj := a.obj
+ tempKey := a.key
+
+ a.obj = b.obj
+ a.key = b.key
+ b.obj = tempObj
+ b.key = tempKey
+
+ if a.rank > r.maxCount {
+ delete(r.dataDict, a.key)
+ dm = a
+ } else {
+ r.dataDict[a.key] = a
+ }
+ if b.rank > r.maxCount {
+ delete(r.dataDict, b.key)
+ dm = b
+ } else {
+ r.dataDict[b.key] = b
+ }
+
+ return
+}
diff --git a/.svn/pristine/2a/2a56a5647a58e684f5d5c35587c678482c56dc2d.svn-base b/.svn/pristine/2a/2a56a5647a58e684f5d5c35587c678482c56dc2d.svn-base
new file mode 100644
index 0000000..160dfa8
--- /dev/null
+++ b/.svn/pristine/2a/2a56a5647a58e684f5d5c35587c678482c56dc2d.svn-base
@@ -0,0 +1,32 @@
+package verifyMgr
+
+import (
+ "fmt"
+ "testing"
+
+ "Framework/managecenterMgr"
+)
+
+func init() {
+ manageCenterDataSwitchObj := &managecenterMgr.ManageCenterDataSwitch{
+ AllDataSwitch: true,
+ }
+ managecenterMgr.Start("https://managecentertest-fzxh.public.com", manageCenterDataSwitchObj)
+}
+
+func TestVerify(t *testing.T) {
+ if errList := Verify(); len(errList) > 0 {
+ t.Errorf("there should be no error, but now has")
+ for _, err := range errList {
+ fmt.Println(err)
+ }
+ }
+
+ Init("http://www.baidu.com", Con_Get)
+ if errList := Verify(); len(errList) > 0 {
+ t.Errorf("there should be no error, but now has")
+ for _, err := range errList {
+ fmt.Println(err)
+ }
+ }
+}
diff --git a/.svn/pristine/2a/2a62442565a8992159b26fd4bcb62dd98d3f8e35.svn-base b/.svn/pristine/2a/2a62442565a8992159b26fd4bcb62dd98d3f8e35.svn-base
new file mode 100644
index 0000000..c07a12b
--- /dev/null
+++ b/.svn/pristine/2a/2a62442565a8992159b26fd4bcb62dd98d3f8e35.svn-base
@@ -0,0 +1,14 @@
+package yamlUtil
+
+import (
+ "fmt"
+ "goutil/jsonUtil"
+ "testing"
+)
+
+func TestLoadYaml(t *testing.T) {
+ config, _ := LoadFromFile("config.yaml")
+ configStr, _ := jsonUtil.DeepClone(config)
+
+ fmt.Print(configStr)
+}
diff --git a/.svn/pristine/2b/2ba46d976f1f72118d5726c9a45ee3c678037629.svn-base b/.svn/pristine/2b/2ba46d976f1f72118d5726c9a45ee3c678037629.svn-base
new file mode 100644
index 0000000..88ad604
--- /dev/null
+++ b/.svn/pristine/2b/2ba46d976f1f72118d5726c9a45ee3c678037629.svn-base
@@ -0,0 +1,295 @@
+package build
+
+import (
+ "fmt"
+ "reflect"
+ "strconv"
+
+ "goutil/xmlUtil/gxpath/internal/query"
+)
+
+// valueType is a return value type.
+type valueType int
+
+const (
+ booleanType valueType = iota
+ numberType
+ stringType
+ nodeSetType
+)
+
+func getValueType(i interface{}) valueType {
+ v := reflect.ValueOf(i)
+ switch v.Kind() {
+ case reflect.Float64:
+ return numberType
+ case reflect.String:
+ return stringType
+ case reflect.Bool:
+ return booleanType
+ default:
+ if _, ok := i.(query.Query); ok {
+ return nodeSetType
+ }
+ }
+ panic(fmt.Errorf("xpath unknown value type: %v", v.Kind()))
+}
+
+type logical func(query.Iterator, string, interface{}, interface{}) bool
+
+var logicalFuncs = [][]logical{
+ []logical{cmpBoolean_Boolean, nil, nil, nil},
+ []logical{nil, cmpNumeric_Numeric, cmpNumeric_String, cmpNumeric_NodeSet},
+ []logical{nil, cmpString_Numeric, cmpString_String, cmpString_NodeSet},
+ []logical{nil, cmpNodeSet_Numeric, cmpNodeSet_String, cmpNodeSet_NodeSet},
+}
+
+// number vs number
+func cmpNumberNumberF(op string, a, b float64) bool {
+ switch op {
+ case "=":
+ return a == b
+ case ">":
+ return a > b
+ case "<":
+ return a < b
+ case ">=":
+ return a >= b
+ case "<=":
+ return a <= b
+ case "!=":
+ return a != b
+ }
+ return false
+}
+
+// string vs string
+func cmpStringStringF(op string, a, b string) bool {
+ switch op {
+ case "=":
+ return a == b
+ case ">":
+ return a > b
+ case "<":
+ return a < b
+ case ">=":
+ return a >= b
+ case "<=":
+ return a <= b
+ case "!=":
+ return a != b
+ }
+ return false
+}
+
+func cmpBooleanBooleanF(op string, a, b bool) bool {
+ switch op {
+ case "or":
+ return a || b
+ case "and":
+ return a && b
+ }
+ return false
+}
+
+func cmpNumeric_Numeric(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(float64)
+ b := n.(float64)
+ return cmpNumberNumberF(op, a, b)
+}
+
+func cmpNumeric_String(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(float64)
+ b := n.(string)
+ num, err := strconv.ParseFloat(b, 64)
+ if err != nil {
+ panic(err)
+ }
+ return cmpNumberNumberF(op, a, num)
+}
+
+func cmpNumeric_NodeSet(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(float64)
+ b := n.(query.Query)
+
+ for {
+ node := b.Select(t)
+ if node == nil {
+ break
+ }
+ num, err := strconv.ParseFloat(node.Value(), 64)
+ if err != nil {
+ panic(err)
+ }
+ if cmpNumberNumberF(op, a, num) {
+ return true
+ }
+ }
+ return false
+}
+
+func cmpNodeSet_Numeric(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(query.Query)
+ b := n.(float64)
+ for {
+ node := a.Select(t)
+ if node == nil {
+ break
+ }
+ num, err := strconv.ParseFloat(node.Value(), 64)
+ if err != nil {
+ panic(err)
+ }
+ if cmpNumberNumberF(op, num, b) {
+ return true
+ }
+ }
+ return false
+}
+
+func cmpNodeSet_String(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(query.Query)
+ b := n.(string)
+ for {
+ node := a.Select(t)
+ if node == nil {
+ break
+ }
+ if cmpStringStringF(op, b, node.Value()) {
+ return true
+ }
+ }
+ return false
+}
+
+func cmpNodeSet_NodeSet(t query.Iterator, op string, m, n interface{}) bool {
+ return false
+}
+
+func cmpString_Numeric(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(string)
+ b := n.(float64)
+ num, err := strconv.ParseFloat(a, 64)
+ if err != nil {
+ panic(err)
+ }
+ return cmpNumberNumberF(op, b, num)
+}
+
+func cmpString_String(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(string)
+ b := n.(string)
+ return cmpStringStringF(op, a, b)
+}
+
+func cmpString_NodeSet(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(string)
+ b := n.(query.Query)
+ for {
+ node := b.Select(t)
+ if node == nil {
+ break
+ }
+ if cmpStringStringF(op, a, node.Value()) {
+ return true
+ }
+ }
+ return false
+}
+
+func cmpBoolean_Boolean(t query.Iterator, op string, m, n interface{}) bool {
+ a := m.(bool)
+ b := n.(bool)
+ return cmpBooleanBooleanF(op, a, b)
+}
+
+// eqFunc is an `=` operator.
+func eqFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, "=", m, n)
+}
+
+// gtFunc is an `>` operator.
+func gtFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, ">", m, n)
+}
+
+// geFunc is an `>=` operator.
+func geFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, ">=", m, n)
+}
+
+// ltFunc is an `<` operator.
+func ltFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, "<", m, n)
+}
+
+// leFunc is an `<=` operator.
+func leFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, "<=", m, n)
+}
+
+// neFunc is an `!=` operator.
+func neFunc(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, "!=", m, n)
+}
+
+// orFunc is an `or` operator.
+var orFunc = func(t query.Iterator, m, n interface{}) interface{} {
+ t1 := getValueType(m)
+ t2 := getValueType(n)
+ return logicalFuncs[t1][t2](t, "or", m, n)
+}
+
+func numericExpr(m, n interface{}, cb func(float64, float64) float64) float64 {
+ typ := reflect.TypeOf(float64(0))
+ a := reflect.ValueOf(m).Convert(typ)
+ b := reflect.ValueOf(n).Convert(typ)
+ return cb(a.Float(), b.Float())
+}
+
+// plusFunc is an `+` operator.
+var plusFunc = func(m, n interface{}) interface{} {
+ return numericExpr(m, n, func(a, b float64) float64 {
+ return a + b
+ })
+}
+
+// minusFunc is an `-` operator.
+var minusFunc = func(m, n interface{}) interface{} {
+ return numericExpr(m, n, func(a, b float64) float64 {
+ return a - b
+ })
+}
+
+// mulFunc is an `*` operator.
+var mulFunc = func(m, n interface{}) interface{} {
+ return numericExpr(m, n, func(a, b float64) float64 {
+ return a * b
+ })
+}
+
+// divFunc is an `DIV` operator.
+var divFunc = func(m, n interface{}) interface{} {
+ return numericExpr(m, n, func(a, b float64) float64 {
+ return a / b
+ })
+}
+
+// modFunc is an 'MOD' operator.
+var modFunc = func(m, n interface{}) interface{} {
+ return numericExpr(m, n, func(a, b float64) float64 {
+ return float64(int(a) % int(b))
+ })
+}
diff --git a/.svn/pristine/2c/2c280202647fe7e9eb22c3f13cd5afd8135b0dab.svn-base b/.svn/pristine/2c/2c280202647fe7e9eb22c3f13cd5afd8135b0dab.svn-base
new file mode 100644
index 0000000..b33943c
--- /dev/null
+++ b/.svn/pristine/2c/2c280202647fe7e9eb22c3f13cd5afd8135b0dab.svn-base
@@ -0,0 +1,91 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4 h1:OoL469zqSNrTLSz5zeVF/I6VOO7fiw2bzSzQe4J557c=
+github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4/go.mod h1:xe9a/L2aeOgFKKgrO3ibQTnMdpAeL0GC+5/HpGScSa4=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+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/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
+github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
+github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
+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/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
+github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
+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.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
+github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
+github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+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.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+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/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
+golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+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/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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
+gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
diff --git a/.svn/pristine/2c/2c42831a7794d3b03ba2af46e7a5709253508107.svn-base b/.svn/pristine/2c/2c42831a7794d3b03ba2af46e7a5709253508107.svn-base
new file mode 100644
index 0000000..f03bf19
--- /dev/null
+++ b/.svn/pristine/2c/2c42831a7794d3b03ba2af46e7a5709253508107.svn-base
@@ -0,0 +1,78 @@
+package jsonUtil
+
+import (
+ "encoding/json"
+ "strings"
+)
+
+// 使用Number类型来反序列化字符串
+// 当被序列化为interface{}类型时,如果int型的长度大于7,则会被使用科学计数法进行表示
+// 当反序列化时,会无法转换为int类型,会导致错误
+// 所以需要使用Number类型
+// s:输入字符串
+// 返回值:
+// 反序列化后的数据
+// 错误对象
+func UnMarshalWithNumberType(s string) (interface{}, error) {
+ // 构造decode对象
+ var decode = json.NewDecoder(strings.NewReader(s))
+ decode.UseNumber()
+
+ // decode
+ var result interface{}
+ if err := decode.Decode(&result); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// 深拷贝对象
+// src:源数据
+// 返回值:
+// 新对象
+// 错误对象
+func DeepClone(src interface{}) (interface{}, error) {
+ var byteSlice []byte
+ var err error
+
+ // 先序列化为[]byte
+ if byteSlice, err = json.Marshal(src); err != nil {
+ return nil, err
+ }
+
+ // 再反序列化成对象
+ var result interface{}
+ if err := json.Unmarshal(byteSlice, &result); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+// 使用Number类型来深拷贝对象
+// src:源数据
+// 返回值:
+// 新对象
+// 错误对象
+func DeepCloneWithNumberType(src interface{}) (interface{}, error) {
+ var byteSlice []byte
+ var err error
+
+ // 先序列化为[]byte
+ if byteSlice, err = json.Marshal(src); err != nil {
+ return nil, err
+ }
+
+ // 构造decode对象
+ var decode = json.NewDecoder(strings.NewReader(string(byteSlice)))
+ decode.UseNumber()
+
+ // decode
+ var result interface{}
+ if err := decode.Decode(&result); err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/.svn/pristine/2d/2de0a01a0fa2a5a57e9f7e655eb3d363f14c41be.svn-base b/.svn/pristine/2d/2de0a01a0fa2a5a57e9f7e655eb3d363f14c41be.svn-base
new file mode 100644
index 0000000..b47db9a
--- /dev/null
+++ b/.svn/pristine/2d/2de0a01a0fa2a5a57e9f7e655eb3d363f14c41be.svn-base
@@ -0,0 +1,6 @@
+package exitMgr
+
+// 程序退出包,提供程序退出时的功能
+// 使用方法:
+// 1、先调用RegisterExitFunc方法,将系统退出时需要调用的方法进行注册。
+// 2、在程序退出时调用Exit()方法
diff --git a/.svn/pristine/2d/2de12c2ba27e67d1efdfc163a25f3b7bd611f8a6.svn-base b/.svn/pristine/2d/2de12c2ba27e67d1efdfc163a25f3b7bd611f8a6.svn-base
new file mode 100644
index 0000000..8410351
--- /dev/null
+++ b/.svn/pristine/2d/2de12c2ba27e67d1efdfc163a25f3b7bd611f8a6.svn-base
@@ -0,0 +1,57 @@
+package logUtil
+
+import (
+ "goutil/logUtil/impl-localfile"
+)
+
+// 定义一个全局的日志对象
+var (
+ // 日志列表
+ logs []ILog
+
+ // 文件log
+ fileLog *impl_localfile.Logger
+)
+
+func init() {
+ // 提供默认的日志对象
+ fileLog = impl_localfile.NewLogger()
+ logs = append(logs, fileLog)
+}
+
+// AddLogger
+// @description: 添加日志对象
+// parameter:
+//
+// @l:日志实现
+//
+// return:
+func SettingLogs(_logs []ILog) {
+ if _logs == nil || len(_logs) == 0 {
+ panic("_logs不能为nil或者len(_logs)==0")
+ }
+
+ logs = _logs
+}
+
+// GetLocalFileLog
+// @description: 获取文件日志对象
+// parameter:
+// return:
+//
+// @*log_localfile.Logger:
+func GetLocalFileLog() *impl_localfile.Logger {
+ return fileLog
+}
+
+// SetLogPath
+// @description: 设置文件日志路径
+// parameter:
+//
+// @_logPath:路径
+//
+// return:
+// Deprecated: use GetLocalFileLog().SetLogPath(_logPath) api instead
+func SetLogPath(_logPath string) {
+ fileLog.SetLogPath(_logPath)
+}
diff --git a/.svn/pristine/2e/2e2532365bcd2cea0e001934e67db11e0fea1405.svn-base b/.svn/pristine/2e/2e2532365bcd2cea0e001934e67db11e0fea1405.svn-base
new file mode 100644
index 0000000..dc86fb1
--- /dev/null
+++ b/.svn/pristine/2e/2e2532365bcd2cea0e001934e67db11e0fea1405.svn-base
@@ -0,0 +1,78 @@
+package stringUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestSplit(t *testing.T) {
+ s := "1,2;3|4||5,6;7|8||9,"
+ // seps := []string{",", ";", "|", "||"}
+ retList := Split(s, nil)
+ if retList[0] != "1" || retList[1] != "2" || retList[2] != "3" || retList[3] != "4" || retList[4] != "5" || retList[5] != "6" || retList[6] != "7" || retList[7] != "8" || retList[8] != "9" {
+ t.Errorf("ecptected:123456789, but now got:%v", retList)
+ }
+}
+
+func TestSplitToIntSlice(t *testing.T) {
+ s := "1, 2, 3, 4, 5, a"
+ if _, err := SplitToIntSlice(s, ","); err == nil {
+ t.Errorf("Expected got err, but got nil")
+ }
+
+ s = "1, 5, 39,"
+ if intSlice, err := SplitToIntSlice(s, ","); err != nil {
+ t.Errorf("Expected got nil, but got error:%s", err)
+ } else {
+ // fmt.Printf("intSlice:%v\n", intSlice)
+ if intSlice[0] != 1 || intSlice[1] != 5 || intSlice[2] != 39 {
+ t.Errorf("Expected got %s, but got %v", s, intSlice)
+ }
+ }
+}
+
+func TestSplitToIntRegion(t *testing.T) {
+ idRegionStr := ""
+ outerSep := ","
+ innerSep := "-"
+ var err error
+
+ if _, err = SplitToIntRegion(idRegionStr, outerSep, innerSep); err == nil {
+ t.Errorf("PraseIdRegion should failed, but now not.err:%s", err)
+ }
+
+ idRegionStr = ","
+ if _, err = SplitToIntRegion(idRegionStr, outerSep, innerSep); err == nil {
+ t.Errorf("PraseIdRegion should failed, but now not.err:%s", err)
+ }
+
+ idRegionStr = "1-100,101,200"
+ if _, err = SplitToIntRegion(idRegionStr, outerSep, innerSep); err == nil {
+ t.Errorf("PraseIdRegion should failed, but now not.err:%s", err)
+ }
+
+ idRegionStr = "1-100,101-20"
+ if _, err = SplitToIntRegion(idRegionStr, outerSep, innerSep); err == nil {
+ t.Errorf("PraseIdRegion should failed, but now not.err:%s", err)
+ }
+
+ idRegionStr = "1-100,101-200"
+ if idRegionList, err := SplitToIntRegion(idRegionStr, outerSep, innerSep); err != nil {
+ t.Errorf("PraseIdRegion should succeed, but now failed.err:%s", err)
+ } else {
+ if idRegionList[0].Lower != 1 || idRegionList[0].Upper != 100 ||
+ idRegionList[1].Lower != 101 || idRegionList[1].Upper != 200 {
+ t.Errorf("SplitToIntRegion should succeed, but now failed. idRegionStr:%s, idRegionList:%v", idRegionStr, idRegionList)
+ }
+ }
+}
+
+func TestSplitToFloat64(t *testing.T) {
+ result, err := SplitToFloat64Slice("1.11,2.22", ",")
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ fmt.Printf("%v\n", result)
+}
diff --git a/.svn/pristine/2e/2e766b25919f4eac85c32fd101e5bd303ef1190c.svn-base b/.svn/pristine/2e/2e766b25919f4eac85c32fd101e5bd303ef1190c.svn-base
new file mode 100644
index 0000000..a3b48b2
--- /dev/null
+++ b/.svn/pristine/2e/2e766b25919f4eac85c32fd101e5bd303ef1190c.svn-base
@@ -0,0 +1,4 @@
+/*
+数据类型转换类(主要针对interface)
+*/
+package typeUtil
diff --git a/.svn/pristine/2e/2e8e3f2c21083bfc1741db5df016b198b53ae6ad.svn-base b/.svn/pristine/2e/2e8e3f2c21083bfc1741db5df016b198b53ae6ad.svn-base
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.svn/pristine/2e/2e8e3f2c21083bfc1741db5df016b198b53ae6ad.svn-base
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.svn/pristine/2e/2eb9ec388af8b1eec3c306160021488411784adb.svn-base b/.svn/pristine/2e/2eb9ec388af8b1eec3c306160021488411784adb.svn-base
new file mode 100644
index 0000000..5b6a313
--- /dev/null
+++ b/.svn/pristine/2e/2eb9ec388af8b1eec3c306160021488411784adb.svn-base
@@ -0,0 +1,54 @@
+package fileUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestGzip(t *testing.T) {
+ path := GetCurrentPath()
+ fmt.Printf("CurrPath:%s\n", path)
+
+ fileName := fmt.Sprintf("%s/%s", path, "test.txt")
+ if err := WriteFile(path, "test.txt", true, "first line\nHello world"); err != nil {
+ t.Errorf("there should be no error, but now it is:%s", err)
+ }
+
+ if err := Gzip(fileName, ""); err != nil {
+ // if err := Gzip(fileName, path); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ }
+
+ if fileList, err := GetFileList(path); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ } else {
+ for _, item := range fileList {
+ fmt.Printf("item:%s\n", item)
+ }
+ }
+
+ DeleteFile(fileName)
+}
+
+func TestUnGzip(t *testing.T) {
+ path := GetCurrentPath()
+ fmt.Printf("CurrPath:%s\n", path)
+
+ fileName := fmt.Sprintf("%s/%s", path, "test.txt.gz")
+ if err := UnGzip(fileName, ""); err != nil {
+ // if err := UnGzip(fileName, path); err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ }
+
+ content, err := ReadFileContent(fmt.Sprintf("%s/%s", path, "test.txt"))
+ if err != nil {
+ t.Errorf("There should be no error, but now it has:%s", err)
+ } else {
+ fmt.Printf("content:%s\n", content)
+ }
+
+ DeleteFile(fileName)
+
+ fileName = fmt.Sprintf("%s/%s", path, "test.txt")
+ DeleteFile(fileName)
+}
diff --git a/.svn/pristine/2e/2ebc67fa9c1257d723c197f604ecb9c540c228fd.svn-base b/.svn/pristine/2e/2ebc67fa9c1257d723c197f604ecb9c540c228fd.svn-base
new file mode 100644
index 0000000..b82cb50
--- /dev/null
+++ b/.svn/pristine/2e/2ebc67fa9c1257d723c197f604ecb9c540c228fd.svn-base
@@ -0,0 +1,313 @@
+package webUtil
+
+import (
+ "bytes"
+ "crypto/tls"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+)
+
+func GetFormHeader() map[string]string {
+ return map[string]string{"Content-Type": "application/x-www-form-urlencoded"}
+}
+
+func GetJsonHeader() map[string]string {
+ return map[string]string{"Content-Type": "application/json;charset=UTF-8"}
+}
+
+// POST数据
+// weburl:远程服务器地址
+// data:post的数据集合
+// header:包头集合
+// 返回值:
+// 返回的字节
+// 错误对象
+func PostWebData(weburl string, data map[string]string, header map[string]string) (result []byte, err error) {
+ // 组装POST数据
+ postValues := url.Values{}
+ for key, value := range data {
+ postValues.Set(key, value)
+ }
+ postDataStr := postValues.Encode()
+ byteData := []byte(postDataStr)
+
+ // 调用发送Byte数组的方法
+ result, err = PostByteData(weburl, byteData, header)
+
+ return
+}
+
+// POST Byte数组
+// weburl:远程服务器地址
+// data:post的Byte数组
+// header:包头集合
+// 返回值:
+// 返回的字节
+// 错误对象
+func PostByteData(weburl string, data []byte, header map[string]string) (result []byte, err error) {
+ // 组装POST数据
+ reader := bytes.NewReader(data)
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("POST", weburl, reader)
+ if err != nil {
+ return
+ }
+
+ // 处理头部(包括默认头部,以及传入的头部集合)
+ if header == nil {
+ for k, v := range GetFormHeader() {
+ request.Header.Add(k, v)
+ }
+ } else {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ transport := NewTransport()
+ transport.DisableKeepAlives = true
+
+ transport = GetTimeoutTransport(transport, 30)
+ transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 读取数据
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
+
+// POST Byte数组
+// weburl:远程服务器地址
+// data:post的Byte数组
+// header:包头集合
+// transport: transport对象
+// 返回值:
+// 返回的字节
+// 错误对象
+func PostByteDataWithTransport(weburl string, data []byte, header map[string]string, transport *http.Transport) (result *[]byte, err error) {
+ // 组装POST数据
+ reader := bytes.NewReader(data)
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("POST", weburl, reader)
+ if err != nil {
+ return
+ }
+
+ // 处理头部
+ if header != nil {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ if transport == nil {
+ transport = NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+ transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
+ }
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ body, err1 := ioutil.ReadAll(response.Body)
+ if err1 != nil {
+ err = err1
+ return
+ }
+
+ result = &body
+
+ return
+}
+
+// POST map类型的数据
+// weburl:远程服务器地址
+// data:数据
+// header:包头内容
+// transport:transport对象
+// 返回值
+// http StatusCode
+// 字节数组
+// 错误对象
+func PostMapData(weburl string, data map[string]string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
+ // 组装POST数据
+ postValues := url.Values{}
+ for key, value := range data {
+ postValues.Set(key, value)
+ }
+ postDataStr := postValues.Encode()
+ byteData := []byte(postDataStr)
+
+ statusCode, result, err = PostByteData2(weburl, byteData, header, transport)
+ return
+}
+
+// POST byte类型的数据(新方法)
+// weburl:远程服务器地址
+// data:数据
+// header:包头内容
+// transport:transport对象
+// 返回值
+// http StatusCode
+// 字节数组
+// 错误对象
+func PostByteData2(weburl string, data []byte, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
+ // 组装POST数据
+ reader := bytes.NewReader(data)
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("POST", weburl, reader)
+ if err != nil {
+ return
+ }
+
+ // 处理头部
+ if header != nil {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ if transport == nil {
+ transport = NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+ transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //关闭证书校验
+ }
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 获取返回值
+ statusCode = response.StatusCode
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
+
+// POST Byte数组
+// weburl:远程服务器地址
+// data:post的Byte数组
+// header:包头集合
+// 返回值:
+// 返回的字节
+// 错误对象
+func PostByteData3(weburl string, data []byte, header map[string]string) (result []byte, err error) {
+ // 组装POST数据
+ reader := bytes.NewReader(data)
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("POST", weburl, reader)
+ if err != nil {
+ return
+ }
+
+ request.Header.Set("Content-Type", "application/json;charset=UTF-8")
+
+ // 构造transport对象
+ transport := NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+ transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 读取数据
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
+
+// POST Byte数组
+// weburl:远程服务器地址
+// data:post的Byte数组
+// header:包头集合
+// timeout:超时时间
+// 返回值:
+// 返回的字节
+// 错误对象
+func PostByteData4(weburl string, data []byte, header map[string]string, timeout int) (result []byte, err error) {
+ // 组装POST数据
+ reader := bytes.NewReader(data)
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("POST", weburl, reader)
+ if err != nil {
+ return
+ }
+
+ request.Header.Set("Content-Type", "application/json;charset=UTF-8")
+
+ // 构造transport对象
+ if timeout <= 0 {
+ timeout = 30
+ }
+ transport := NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, timeout)
+ transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 读取数据
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
diff --git a/.svn/pristine/2f/2f14ad8b60fa320c31dece98ac92ee259e9a5f3e.svn-base b/.svn/pristine/2f/2f14ad8b60fa320c31dece98ac92ee259e9a5f3e.svn-base
new file mode 100644
index 0000000..7cba3dc
--- /dev/null
+++ b/.svn/pristine/2f/2f14ad8b60fa320c31dece98ac92ee259e9a5f3e.svn-base
@@ -0,0 +1,40 @@
+package securityUtil
+
+import (
+ "crypto/sha256"
+ "errors"
+ "fmt"
+)
+
+// 对字符串进行SHA256加密,并且可以选择返回大、小写
+// s:输入字符串
+// ifUpper:输出是否大写
+// 返回值:sha256加密后的十六进制字符串
+func Sha256String(s string, ifUpper bool) string {
+ if len(s) == 0 {
+ panic(errors.New("input string can't be empty"))
+ }
+
+ buf := Sha256Bytes([]byte(s))
+
+ if ifUpper {
+ return fmt.Sprintf("%X", buf)
+ } else {
+ return fmt.Sprintf("%x", buf)
+ }
+}
+
+// 对字符数组进行SHA256加密
+// b:输入字符数组
+// 返回值:sha256加密后的原数据
+func Sha256Bytes(b []byte) []byte {
+ if len(b) == 0 {
+ panic(errors.New("input []byte can't be empty"))
+ }
+
+ sha1Instance := sha256.New()
+ sha1Instance.Write(b)
+ result := sha1Instance.Sum(nil)
+
+ return result
+}
diff --git a/.svn/pristine/30/30949ac53c528a2ecc3d58647e3be3906413ea67.svn-base b/.svn/pristine/30/30949ac53c528a2ecc3d58647e3be3906413ea67.svn-base
new file mode 100644
index 0000000..7de2f6d
--- /dev/null
+++ b/.svn/pristine/30/30949ac53c528a2ecc3d58647e3be3906413ea67.svn-base
@@ -0,0 +1,135 @@
+package util
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "strings"
+
+ "google.golang.org/grpc/peer"
+ "google.golang.org/protobuf/encoding/protojson"
+ "google.golang.org/protobuf/proto"
+)
+
+var (
+ moOpt protojson.MarshalOptions
+ uoOpt protojson.UnmarshalOptions
+)
+
+func init() {
+ moOpt = protojson.MarshalOptions{
+ // Multiline: true,
+ AllowPartial: true,
+ UseProtoNames: true,
+ UseEnumNumbers: true,
+ EmitUnpopulated: true,
+ }
+ uoOpt = protojson.UnmarshalOptions{
+ DiscardUnknown: true,
+ }
+}
+
+// PbCopy
+// @description: 将from对象的内容copy给to对象
+// parameter:
+// @from:proto.Message
+// @to:proto.Message
+// return:
+// @error:如果失败,则返回错误,否则返回nil
+func PbCopy(from, to proto.Message) error {
+ data, err := proto.Marshal(from)
+ if err != nil {
+ return err
+ }
+
+ return proto.Unmarshal(data, to)
+}
+
+// Pb2Json
+// @description: 将pb对象转换为json字符串
+// parameter:
+// @m:
+// return:
+// @string:pb对象的json标识形式
+// @error:
+func Pb2Json(m proto.Message) (string, error) {
+ str, err := moOpt.Marshal(m)
+ if err != nil {
+ return "", err
+ }
+
+ return string(str), nil
+}
+
+// Json2Pb
+// @description: 将json字符串转换成对应pb对象
+// parameter:
+// @js:
+// @m:
+// return:
+// @error:
+func Json2Pb(js string, m proto.Message) error {
+ return uoOpt.Unmarshal([]byte(js), m)
+}
+
+// Marshal
+// @description: 序列化pb对象
+// parameter:
+// @m:
+// return:
+// @[]byte:
+// @error:
+func Marshal(m proto.Message) ([]byte, error) {
+ data, err := proto.Marshal(m)
+ if err != nil {
+ return nil, err
+ }
+
+ return data, nil
+}
+
+// Marshal_Panic
+// @description: 序列化pb对象
+// parameter:
+// @m:
+// return:
+// @[]byte:
+func Marshal_Panic(m proto.Message) []byte {
+ data, err := Marshal(m)
+ if err != nil {
+ panic(fmt.Sprintf("pbUtil Marshal pb错误,err:%s", err))
+ }
+
+ return data
+}
+
+// Unmarshal
+// @description: 将数据转换为pb对象
+// parameter:
+// @data:
+// @m:
+// return:
+func Unmarshal(data []byte, m proto.Message) error {
+ err := proto.Unmarshal(data, m)
+ return err
+}
+
+// GetClientIP
+// @description: 获取客户端Ip
+// parameter:
+// @ctx:grpc底层传递过来的上下文对象
+// return:
+// @string:客户端ip
+// @error:错误对象
+func GetClientIP(ctx context.Context) (string, error) {
+ pr, ok := peer.FromContext(ctx)
+ if !ok {
+ return "", fmt.Errorf("GetClietIP未获取到客户端ip")
+ }
+ if pr.Addr == net.Addr(nil) {
+ return "", fmt.Errorf("GetClientIP 获取到的peer.Addr=nil")
+ }
+ addSlice := strings.Split(pr.Addr.String(), ":")
+
+ return addSlice[0], nil
+}
diff --git a/.svn/pristine/30/30b3aab878ea7aff20885d6b00cc935dbd706a3e.svn-base b/.svn/pristine/30/30b3aab878ea7aff20885d6b00cc935dbd706a3e.svn-base
new file mode 100644
index 0000000..bba1bc3
--- /dev/null
+++ b/.svn/pristine/30/30b3aab878ea7aff20885d6b00cc935dbd706a3e.svn-base
@@ -0,0 +1,15 @@
+package gameServerMgr
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestActive(t *testing.T) {
+ err := ActiveServer("https://managecenterapitest-xxx.79yougame.com/API/ServerActivate.ashx", 20002)
+ if err != nil {
+ fmt.Println("xxx")
+ }
+
+ CheckNewResourceVersion(1001, 20002, 100, "1584085505_769926880ac0ae89a31dcdfef5b94b1e")
+}
diff --git a/.svn/pristine/30/30ba2f04f4755f5db8d0594c2929c51ee463b213.svn-base b/.svn/pristine/30/30ba2f04f4755f5db8d0594c2929c51ee463b213.svn-base
new file mode 100644
index 0000000..82aa9d1
--- /dev/null
+++ b/.svn/pristine/30/30ba2f04f4755f5db8d0594c2929c51ee463b213.svn-base
@@ -0,0 +1,84 @@
+package impl_console
+
+import (
+ "fmt"
+ "github.com/fatih/color"
+)
+
+type Logger struct {
+}
+
+// NewLogger
+// @description: 构造控制台日志
+// parameter:
+// return:
+// @*Logger:
+func NewLogger() *Logger {
+ return &Logger{}
+}
+
+// InfoLog
+// @description: 信息日志记录
+// parameter:
+// @format:日志格式
+// @args:参数列表
+// return:
+func (cl *Logger) InfoLog(format string, args ...interface{}) {
+ c := color.New(color.FgGreen)
+ s := c.Sprint("Info:")
+ fmt.Println(s, fmt.Sprintf(format, args...))
+}
+
+// DebugLog
+// @description: 调试日志记录
+// parameter:
+// @format:日志格式
+// @args:参数列表
+// return:
+func (cl *Logger) DebugLog(format string, args ...interface{}) {
+ c := color.New(color.FgGreen)
+ s := c.Sprint("Debug:")
+ fmt.Println(s, fmt.Sprintf(format, args...))
+}
+
+// WarnLog
+// @description: 警告日志记录
+// parameter:
+// @format:日志格式
+// @args:参数列表
+// return:
+func (cl *Logger) WarnLog(format string, args ...interface{}) {
+ c := color.New(color.FgYellow)
+ _, _ = c.Println("Warn:", fmt.Sprintf(format, args...))
+}
+
+// ErrorLog
+// @description: 错误日志记录
+// parameter:
+// @format:日志格式
+// @args:参数列表
+// return:
+func (cl *Logger) ErrorLog(format string, args ...interface{}) {
+ c := color.New(color.FgRed)
+ _, _ = c.Println("Error:", fmt.Sprintf(format, args...))
+}
+
+// FatalLog
+// @description: 致命错误日志记录
+// parameter:
+// @format:日志格式
+// @args:参数列表
+// return:
+func (cl *Logger) FatalLog(format string, args ...interface{}) {
+ c := color.New(color.FgRed)
+ _, _ = c.Println("Fatal:", fmt.Sprintf(format, args...))
+}
+
+// CloseLog
+// @description: 关闭日志
+// parameter:
+// @waitFinish:是否等待日志
+// return:
+func (cl *Logger) CloseLog(waitFinish bool) {
+
+}
diff --git a/.svn/pristine/30/30fd49aaef962809ed3ade0ffa38bd43ad47b521.svn-base b/.svn/pristine/30/30fd49aaef962809ed3ade0ffa38bd43ad47b521.svn-base
new file mode 100644
index 0000000..a31dd54
--- /dev/null
+++ b/.svn/pristine/30/30fd49aaef962809ed3ade0ffa38bd43ad47b521.svn-base
@@ -0,0 +1,131 @@
+package redisUtil
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/gomodule/redigo/redis"
+)
+
+// 订阅回调函数
+type SubscribeCallback func() error
+
+// Subscriber
+// @description: 订阅者
+type Subscriber struct {
+ // pool 订阅者连接池
+ pool *RedisPool
+ // callBack 订阅者回调函数
+ callBack SubscribeCallback
+}
+
+// NewSubscriber
+// @description: 构建一个订阅者
+// parameter:
+// @pool:
+// @callBack:
+// return:
+// @*Subscriber:
+func NewSubscriber(pool *RedisPool, callBack SubscribeCallback) *Subscriber {
+ return &Subscriber{pool: pool, callBack: callBack}
+}
+
+// Promulgator
+// @description: 发布者
+type Promulgator struct {
+ // pool 发布者连接池
+ pool *RedisPool
+}
+
+// NewPromulgator
+// @description: 构建一个发布者
+// parameter:
+// @pool:
+// return:
+// @*Promulgator:
+func NewPromulgator(pool *RedisPool) *Promulgator {
+ return &Promulgator{pool: pool}
+}
+
+// Publish
+// @description: 发布消息
+// parameter:
+// @receiver s:
+// @channel:
+// @message:
+// return:
+// @error:
+func (s *Promulgator) Publish(channel, message string) error {
+ c := s.pool.GetConnection()
+ defer c.Close()
+
+ _, err := c.Do("PUBLISH", channel, message)
+ if err != nil {
+ return fmt.Errorf("redis publish %s %s, err: %v", channel, message, err)
+ }
+ //n, err := s.pool.Int(result)
+ //if err != nil {
+ // return fmt.Errorf("redis publish %s %s, err: %v", channel, message, err)
+ //}
+
+ return nil
+}
+
+// Subscribe
+// @description: 订阅者订阅消息
+// parameter:
+// @receiver s:
+// @ctx:
+// @channel: 频道
+// return:
+// @error:
+func (s *Subscriber) Subscribe(ctx context.Context, channel ...string) error {
+ sub := redis.PubSubConn{Conn: s.pool.GetConnection()}
+ if err := sub.Subscribe(redis.Args{}.AddFlat(channel)...); err != nil {
+ return err
+ }
+ done := make(chan error, 1)
+
+ // 启动一个新协程去持续订阅消息
+ go func() {
+ defer sub.Close()
+ for {
+ switch msg := sub.Receive().(type) {
+ case error:
+ done <- fmt.Errorf("redis pubsub receive err: %v", msg)
+ return
+ case redis.Message:
+ if err := s.callBack(); err != nil {
+ done <- err
+ return
+ }
+ case redis.Subscription:
+ if msg.Count == 0 {
+ // 所有的订阅者都退出
+ done <- nil
+ return
+ }
+ }
+ }
+ }()
+
+ // health check
+ tick := time.NewTicker(time.Minute)
+ defer tick.Stop()
+ for {
+ select {
+ case <-ctx.Done():
+ if err := sub.Unsubscribe(); err != nil {
+ return fmt.Errorf("redis pubsub unsubscribe err: %v", err)
+ }
+ return nil
+ case err := <-done:
+ return err
+ case <-tick.C:
+ if err := sub.Ping(""); err != nil {
+ return err
+ }
+ }
+ }
+}
diff --git a/.svn/pristine/31/313f27b5bd4317d500dc2743379a8be288c087a9.svn-base b/.svn/pristine/31/313f27b5bd4317d500dc2743379a8be288c087a9.svn-base
new file mode 100644
index 0000000..832f309
--- /dev/null
+++ b/.svn/pristine/31/313f27b5bd4317d500dc2743379a8be288c087a9.svn-base
@@ -0,0 +1,204 @@
+package logSqlSync
+
+import (
+ "database/sql"
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "Framework/dataSyncMgr/mysqlSync/sqlSync"
+ "goutil/logUtil"
+)
+
+// 同步对象定义
+type SyncObject struct {
+ // 服务器组Id
+ serverGroupId int32
+
+ // 同步数据的存储路径
+ dirPath string
+
+ // 同步数据对象的唯一标识,用于进行重复判断
+ identifier string
+
+ // 数据库对象
+ dbObj *sql.DB
+
+ // 同步信息对象
+ syncingInfoObj *syncingInfo
+
+ // 错误处理对象
+ errorHandleObj *syncErrorInfo
+
+ // 同步对象
+ syncObj *sqlSync.SyncObject
+}
+
+// 初始化
+// baseObj:基础同步对象
+func (this *SyncObject) Init(baseObj *sqlSync.SyncObject) {
+ this.syncObj = baseObj
+
+ // 初始化同步信息对象
+ syncingInfoObj, err := newSyncingInfoObject(this.serverGroupId, this.dbObj)
+ if err != nil {
+ panic(err)
+ }
+ //// 初始化错误处理对象
+ errorHandleObj, err := newSyncErrorInfoObject(this.dbObj)
+ if err != nil {
+ panic(err)
+ }
+ this.syncingInfoObj = syncingInfoObj
+ this.errorHandleObj = errorHandleObj
+
+ // 初始化当前处理的文件
+ fileList := sqlSync.GetDataFileList(this.dirPath)
+ filePath, _ := this.syncingInfoObj.GetSyncingInfo()
+ if len(filePath) < 0 && len(fileList) > 0 {
+ this.syncingInfoObj.Update(fileList[0], 0, nil)
+ }
+}
+
+// 获取正在同步的信息
+// filePath:文件路径
+// offset:文件偏移量
+func (this *SyncObject) GetSyncingInfo() (filePath string, offset int64) {
+ return this.syncingInfoObj.GetSyncingInfo()
+}
+
+// 更新
+// filePath:文件路径
+// offset:文件偏移量
+// tran:事务对象
+// 返回值:
+// error:错误对象
+func (this *SyncObject) Update(filePath string, offset int64, tx *sql.Tx) error {
+ return this.syncingInfoObj.Update(filePath, offset, tx)
+}
+
+// 同步一条sql语句
+// command:待执行的命令
+// filePath:保存路径
+// offset:文件偏移量
+// 返回值:
+// error:错误信息
+func (this *SyncObject) SyncOneSql(command string, filePath string, offset int64) {
+ var err error
+ for {
+ err = sqlSync.ExecuteByTran(this.dbObj, func(tran *sql.Tx) (isCommit bool, err error) {
+ // 保存sql到数据库
+ err = this.syncToMysql(command, tran)
+ if err != nil {
+ return
+ }
+
+ // 保存进度信息到数据库
+ err = this.syncingInfoObj.Update(filePath, offset, tran)
+ if err != nil {
+ return
+ }
+
+ isCommit = true
+ return
+ })
+
+ // 如果是连接出错,则仍然循环执行
+ if err != nil {
+ if sqlSync.CheckIfConnectionError(err.Error()) {
+ time.Sleep(5 * time.Second)
+ continue
+ }
+ }
+
+ // 如果不是数据库连接出错,则算是执行完成
+ break
+ }
+
+ // 如果存在错误,则循环尝试执行
+ if err != nil {
+ this.recordSqlError(command, filePath, offset, err.Error())
+ }
+
+ return
+}
+
+// 同步数据到mysql中
+// command:sql语句
+// tx:事务处理对象
+// 返回值:
+// error:错误信息
+func (this *SyncObject) syncToMysql(command string, tx *sql.Tx) error {
+ _, err := tx.Exec(command)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("mysqlSync/logSqlSync/syncObject.syncToMysql error:%s", err.Error()))
+ return err
+ }
+
+ return nil
+}
+
+// 错误处理
+// cmd:待执行的命令
+// filePath:保存路径
+// offset:文件偏移量
+// errMsg:错误信息
+func (this *SyncObject) recordSqlError(command string, filePath string, offset int64, errMsg string) {
+ errMsg = sqlSync.GetSimpleErrorMessage(errMsg)
+
+ for {
+ err := sqlSync.ExecuteByTran(this.dbObj, func(tran *sql.Tx) (isCommit bool, err error) {
+ // 保存sql到数据库
+ err = this.errorHandleObj.AddErrorSql(tran, command, errMsg)
+ if err != nil {
+ return
+ }
+
+ // 保存进度信息到数据库
+ err = this.syncingInfoObj.Update(filePath, offset, tran)
+ if err != nil {
+ return
+ }
+
+ isCommit = true
+ return
+ })
+
+ if err == nil {
+ return
+ }
+
+ time.Sleep(5 * time.Second)
+ }
+}
+
+// 创新新的mysql同步对象
+// dirPath:存放数据的目录
+// identifier:当前数据的唯一标识(可以使用数据库表名)
+// dbObj:数据库对象
+// syncingInfoObj:同步信息记录对象
+// errorHandleObj:错误处理对象
+// 返回值:
+// mysql同步对象
+func NewSyncObject(serverGroupId int32, dirPath, identifier string, dbObj *sql.DB) *SyncObject {
+ dirPath = filepath.Join(dirPath, identifier)
+
+ // 创建更新目录
+ err := os.MkdirAll(dirPath, os.ModePerm|os.ModeTemporary)
+ if err != nil {
+ err = fmt.Errorf("%s-%s-make dir failed:%s", identifier, "SyncObject.newSyncObject.os.MkdirAll", err)
+ logUtil.ErrorLog(err.Error())
+ panic(err)
+ }
+
+ // 构造同步信息对象
+ result := &SyncObject{
+ serverGroupId: serverGroupId,
+ dirPath: dirPath,
+ identifier: identifier,
+ dbObj: dbObj,
+ }
+
+ return result
+}
diff --git a/.svn/pristine/31/3167307a52e20e4a543ae33d5269808f02e5b7e4.svn-base b/.svn/pristine/31/3167307a52e20e4a543ae33d5269808f02e5b7e4.svn-base
new file mode 100644
index 0000000..82ce3b9
--- /dev/null
+++ b/.svn/pristine/31/3167307a52e20e4a543ae33d5269808f02e5b7e4.svn-base
@@ -0,0 +1,101 @@
+package bytesSendUtil
+
+import (
+ "goutil/zlibUtil"
+)
+
+type dataItem interface {
+ // 返回原始数据
+ OriginData() []byte
+
+ // 返回发送字节流
+ Bytes() []byte
+
+ // 设置发送次数
+ SetCount(uint)
+
+ // 返回发送次数
+ Count() uint
+}
+
+/////////////////////////////////////////////////
+// httpDataItem
+
+type httpDataItem struct {
+ // 数据
+ data []byte
+
+ // 发送次数
+ count uint
+}
+
+func newHTTPData(_data []byte) dataItem {
+ return &httpDataItem{
+ data: _data,
+ count: 0,
+ }
+}
+
+// 返回原始数据
+func (this *httpDataItem) OriginData() []byte {
+ return this.data
+}
+
+// 返回原始数据用于发送
+func (this *httpDataItem) Bytes() []byte {
+ return this.data
+}
+
+func (this *httpDataItem) SetCount(cnt uint) {
+ this.count = cnt
+}
+
+func (this *httpDataItem) Count() uint {
+ return this.count
+}
+
+/////////////////////////////////////////////////
+// tcpDataItem
+
+type tcpDataItem struct {
+ // 原始数据
+ origin []byte
+
+ // 压缩后数据
+ data []byte
+
+ // 重试次数
+ count uint
+}
+
+func newTCPDataItem(_data []byte) (dataItem, error) {
+ compressed, err := zlibUtil.Compress([]byte(_data), 5)
+ if err != nil {
+ return nil, err
+ }
+
+ item := &tcpDataItem{
+ origin: _data,
+ data: compressed,
+ count: 0,
+ }
+ return item, nil
+}
+
+// 返回原始数据
+func (this *tcpDataItem) OriginData() []byte {
+ return this.origin
+}
+
+// 返回压缩数据用于发送
+func (this *tcpDataItem) Bytes() []byte {
+ return this.data
+}
+
+func (this *tcpDataItem) SetCount(cnt uint) {
+ this.count = cnt
+}
+
+func (this *tcpDataItem) Count() uint {
+ return this.count
+}
diff --git a/.svn/pristine/33/335a13f982390c2ec9a716fcddcea8bc20697680.svn-base b/.svn/pristine/33/335a13f982390c2ec9a716fcddcea8bc20697680.svn-base
new file mode 100644
index 0000000..7f68c50
--- /dev/null
+++ b/.svn/pristine/33/335a13f982390c2ec9a716fcddcea8bc20697680.svn-base
@@ -0,0 +1,183 @@
+package mqMgr
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ amqp "github.com/rabbitmq/amqp091-go"
+)
+
+// Queue对象
+type HSYQueue struct {
+ conn *amqp.Connection
+ channel *amqp.Channel
+ // 队列名称
+ queueName string
+ // 交换机
+ exchange string
+ // routing Key
+ routingKey string
+ //MQ链接字符串
+ mqurl string
+}
+
+// 消息队列配置对象
+type HSYQueueConfig struct {
+ QueueName string
+ Exchange string
+ RoutingKey string
+ Network string
+ Port int
+ UserName string
+ Password string
+}
+
+// 创建新的Queue对象
+func NewHSYQueue(queueName, exchange, routingKey, userName, password string, network string, port int) *HSYQueue {
+ queueConfigObj := &HSYQueueConfig{
+ QueueName: queueName,
+ Exchange: exchange,
+ RoutingKey: routingKey,
+ UserName: userName,
+ Password: password,
+ Network: network,
+ Port: port,
+ }
+
+ return NewHSYQueueByConfig(queueConfigObj)
+}
+
+// 通过队列配置对象创建新的Queue对象
+func NewHSYQueueByConfig(queueConfigObj *HSYQueueConfig) *HSYQueue {
+ queueObj := &HSYQueue{
+ queueName: queueConfigObj.QueueName,
+ exchange: queueConfigObj.Exchange,
+ routingKey: queueConfigObj.RoutingKey,
+ mqurl: fmt.Sprintf("amqp://%s:%s@%s:%d/", queueConfigObj.UserName, queueConfigObj.Password, queueConfigObj.Network, queueConfigObj.Port),
+ }
+
+ if err := queueObj.GetQueueAttributes(); err != nil {
+ return nil
+ }
+
+ return queueObj
+}
+
+// 连接RabbitMQ服务器
+func (this *HSYQueue) GetQueueAttributes() (err error) {
+ this.conn, err = amqp.Dial(this.mqurl)
+ if err != nil {
+ return
+ }
+
+ this.channel, err = this.conn.Channel()
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+// 释放连接
+func (this *HSYQueue) ReleaseRes() {
+ this.conn.Close()
+ this.channel.Close()
+}
+
+// SendMessage 发送单条消息
+func (this *HSYQueue) SendMessage(message string, ex string) (err error) {
+ // 声明队列
+ _, err = this.channel.QueueDeclare(
+ this.queueName, // 队列名
+ true, // 是否持久化
+ false, // 是否自动删除(前提是至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。注意:生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列)
+ false, // 是否为排他队列(排他的队列仅对“首次”声明的conn可见[一个conn中的其他channel也能访问该队列],conn结束后队列删除)
+ false, // 是否阻塞
+ nil, // 额外属性
+ )
+ if err != nil {
+ err = errors.New("声明队列失败")
+ return
+ }
+
+ // 声明交换器
+ err = this.channel.ExchangeDeclare(
+ this.exchange, //交换器名
+ ex, //exchange type:一般用fanout、direct、topic
+ true, // 是否持久化
+ false, //是否自动删除(自动删除的前提是至少有一个队列或者交换器与这和交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑)
+ false, //设置是否内置的。true表示是内置的交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式
+ false, // 是否阻塞
+ nil, // 额外属性
+ )
+ if err != nil {
+ err = errors.New("声明交换器失败")
+ return
+ }
+
+ // Binding
+ err = this.channel.QueueBind(
+ this.queueName, // 绑定的队列名称
+ this.routingKey, // bindkey 用于消息路由分发的key
+ this.exchange, // 绑定的exchange名
+ false, // 是否阻塞
+ nil, // 额外属性
+ )
+ if err != nil {
+ err = errors.New("绑定队列和交换器失败")
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ err = this.channel.PublishWithContext(ctx,
+ this.exchange,
+ this.routingKey,
+ false,
+ false,
+ amqp.Publishing{
+ ContentType: "text/plain",
+ Body: []byte(message),
+ })
+ if err != nil {
+ err = errors.New("发布消息失败")
+ return
+ }
+
+ return
+}
+
+// ReceiveMessage 消费单条消息
+func (this *HSYQueue) ReceiveMessage() (msgs <-chan amqp.Delivery, err error) {
+ _, err = this.channel.QueueDeclare(
+ this.queueName, // 队列名
+ true, // 是否持久化
+ false, // 是否自动删除(前提是至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。注意:生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列)
+ false, // 是否为排他队列(排他的队列仅对“首次”声明的conn可见[一个conn中的其他channel也能访问该队列],conn结束后队列删除)
+ false, // 是否阻塞
+ nil, // 额外属性(我还不会用)
+ )
+ if err != nil {
+ err = errors.New("声明队列失败")
+ return
+ }
+
+ msgs, err = this.channel.Consume(
+ this.queueName, // 队列名
+ "", // 消费者名,用来区分多个消费者,以实现公平分发或均等分发策略
+ true, // 是否自动应答
+ false, // 是否排他
+ false, // 是否接收只同一个连接中的消息,若为true,则只能接收别的conn中发送的消息
+ true, // 队列消费是否阻塞
+ nil, // 额外属性
+ )
+ if err != nil {
+ err = errors.New("获取消息失败")
+ return
+ }
+
+ return
+}
diff --git a/.svn/pristine/33/33b2559f92484c30f0522d74cc475fcffe1f82f7.svn-base b/.svn/pristine/33/33b2559f92484c30f0522d74cc475fcffe1f82f7.svn-base
new file mode 100644
index 0000000..a5085f2
--- /dev/null
+++ b/.svn/pristine/33/33b2559f92484c30f0522d74cc475fcffe1f82f7.svn-base
@@ -0,0 +1,142 @@
+package stringUtil
+
+import (
+ "regexp"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+// 检查一个字符串是否是空字符串
+// content:上下文字符串
+// 返回值:
+// bool:true:空字符串 false:非空字符串
+func IsEmpty(content string) bool {
+ if len(content) <= 0 {
+ return true
+ }
+
+ return strings.IndexFunc(content, func(item rune) bool {
+ return unicode.IsSpace(item) == false
+ }) < 0
+}
+
+// 截取字符串
+// start:开始位置
+// length:截取长度
+// 返回值:
+// 截取后的字符串
+func Substring(str string, start, length int) string {
+ // 先将字符串转化为[]rune格式(由于rune是字符串的基本单位)
+ runeString := []rune(str)
+ runeLength := len(runeString)
+ end := 0
+
+ // 计算起始位置
+ if start > runeLength {
+ start = runeLength
+ }
+
+ // 计算终止位置
+ end = start + length
+ if end > runeLength {
+ end = runeLength
+ }
+
+ if start > end {
+ start, end = end, start
+ }
+
+ return string(runeString[start:end])
+}
+
+// 根据不同平台获取换行符
+// 返回值:
+// 换行符
+func GetNewLineString() string {
+ switch os := runtime.GOOS; os {
+ case "windows":
+ return "\r\n"
+ default:
+ return "\n"
+ }
+}
+
+// 检查是否存在特殊符号
+// 1. emoji字符
+// 2. ascii控制字符
+// 3. \ " '
+// val:待检查的字符串
+// 返回值:
+// bool:true:有特殊字符 false:无特殊字符
+func IfHaveSpecialChar(val string) bool {
+ if len(val) <= 0 {
+ return false
+ }
+
+ // 表情符号过滤
+ // Wide UCS-4 build
+ emojiReg, _ := regexp.Compile("[^\U00000000-\U0000FFFF]+")
+ if emojiReg.Match([]byte(val)) {
+ return true
+ }
+
+ // 排除控制字符和特殊字符
+ for _, charItem := range val {
+ // 排除控制字符
+ if (charItem > 0 && charItem < 0x20) || charItem == 0x7F {
+ return true
+ }
+
+ // 排除部分特殊字符: \ " '
+ switch charItem {
+ case '\\':
+ fallthrough
+ case '"':
+ fallthrough
+ case '\'':
+ return true
+ }
+ }
+
+ return false
+}
+
+// 判断string数组是否内容唯一
+func IsDistinct_string(list []string) (result bool) {
+ if len(list) == 0 || len(list) == 1 {
+ result = true
+ return
+ }
+
+ sort.Strings(list)
+
+ for i := 0; i < len(list)-1; i++ {
+ if list[i] == list[i+1] {
+ result = false
+ return
+ }
+ }
+
+ result = true
+ return
+}
+
+// 验证是否是电话号码
+func VerifyPhone(phone string) bool {
+ regular := "^1[3-9]\\d{9}$"
+
+ reg := regexp.MustCompile(regular)
+ return reg.MatchString(phone)
+}
+
+// 转型成int64
+func StringToInt64(str string) int64 {
+ num, err := strconv.ParseInt(str, 10, 64)
+ if err != nil {
+ return 0
+ }
+ return num
+}
diff --git a/.svn/pristine/33/33c823dd0646acce265d7166cd02d78a6807aea2.svn-base b/.svn/pristine/33/33c823dd0646acce265d7166cd02d78a6807aea2.svn-base
new file mode 100644
index 0000000..a0802a0
--- /dev/null
+++ b/.svn/pristine/33/33c823dd0646acce265d7166cd02d78a6807aea2.svn-base
@@ -0,0 +1,12 @@
+package managecenterModel
+
+// 服务器状态
+type GroupLoad int32
+
+const (
+ // 正常
+ Con_GroupLoad_Normal GroupLoad = 1
+
+ // 火爆
+ Con_GroupLoad_Hot GroupLoad = 2
+)
diff --git a/.svn/pristine/33/33f4735ef28dd736d756c6d320e069c3ab89f068.svn-base b/.svn/pristine/33/33f4735ef28dd736d756c6d320e069c3ab89f068.svn-base
new file mode 100644
index 0000000..e44e785
--- /dev/null
+++ b/.svn/pristine/33/33f4735ef28dd736d756c6d320e069c3ab89f068.svn-base
@@ -0,0 +1,53 @@
+package mathUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestQuartile(t *testing.T) {
+
+ intList := []int{}
+ var lower, mid, upper float64
+ var err error
+ lower, mid, upper, err = Quartile_Int(intList)
+ if err != nil {
+ fmt.Printf("Error:%s\n", err)
+ }
+
+ intList = []int{4}
+ lower, mid, upper, err = Quartile_Int(intList)
+ if err != nil {
+ fmt.Printf("Error:%s\n", err)
+ }
+ fmt.Printf("LowerQuartile:%f\n", lower)
+ fmt.Printf("MidQuartile:%f\n", mid)
+ fmt.Printf("UpperQuartile:%f\n", upper)
+
+ intList = []int{4, 93}
+ lower, mid, upper, err = Quartile_Int(intList)
+ if err != nil {
+ fmt.Printf("Error:%s\n", err)
+ }
+ fmt.Printf("LowerQuartile:%f\n", lower)
+ fmt.Printf("MidQuartile:%f\n", mid)
+ fmt.Printf("UpperQuartile:%f\n", upper)
+
+ intList = []int{4, 93, 84}
+ lower, mid, upper, err = Quartile_Int(intList)
+ if err != nil {
+ fmt.Printf("Error:%s\n", err)
+ }
+ fmt.Printf("LowerQuartile:%f\n", lower)
+ fmt.Printf("MidQuartile:%f\n", mid)
+ fmt.Printf("UpperQuartile:%f\n", upper)
+
+ intList = []int{4, 93, 84, 85, 80, 37, 81, 93, 27, 12}
+ lower, mid, upper, err = Quartile_Int(intList)
+ if err != nil {
+ fmt.Printf("Error:%s\n", err)
+ }
+ fmt.Printf("LowerQuartile:%f\n", lower)
+ fmt.Printf("MidQuartile:%f\n", mid)
+ fmt.Printf("UpperQuartile:%f\n", upper)
+}
diff --git a/.svn/pristine/34/3439bb7d1781aebf4bed60ed3aadb529219c3f32.svn-base b/.svn/pristine/34/3439bb7d1781aebf4bed60ed3aadb529219c3f32.svn-base
new file mode 100644
index 0000000..99730be
--- /dev/null
+++ b/.svn/pristine/34/3439bb7d1781aebf4bed60ed3aadb529219c3f32.svn-base
@@ -0,0 +1,131 @@
+package jsonUtil
+
+import (
+ "encoding/json"
+ "fmt"
+ "testing"
+)
+
+func TestUnMarshalWithNumberType(t *testing.T) {
+ src := make(map[string]int)
+ src["Name"] = 123
+ src["Money"] = 100000000
+
+ var byteSlice []byte
+ var err error
+ if byteSlice, err = json.Marshal(src); err != nil {
+ t.Errorf("Marshal src failed\n")
+ }
+
+ if target_interface, err := UnMarshalWithNumberType(string(byteSlice)); err != nil {
+ t.Errorf("Expected got nil, but got err:%s\n", err)
+ } else {
+ if target_map, ok := target_interface.(map[string]interface{}); !ok {
+ t.Errorf("Expected got nil, but got err:%s\n", err)
+ } else {
+ money, ok := target_map["Money"].(json.Number)
+ money_int, err := money.Int64()
+ if !ok || err != nil || money_int != 100000000 {
+ t.Errorf("Expected got 100000000, but got %v, ok:%v, err:%s\n", money_int, ok, err)
+ }
+
+ fmt.Printf("target_map:%v\n", target_map)
+ }
+ }
+
+ intSlice1 := []int{1, 2, 3, 5}
+
+ if byteSlice, err = json.Marshal(intSlice1); err != nil {
+ t.Errorf("Marshal src failed\n")
+ }
+
+ if target_interface, err := UnMarshalWithNumberType(string(byteSlice)); err != nil {
+ t.Errorf("Expected got nil, but got err:%s\n", err)
+ } else {
+ fmt.Printf("target_interface:%v\n", target_interface)
+ if target_slice, ok := target_interface.([]interface{}); !ok {
+ t.Errorf("Expected got []int, but failed.\n")
+ } else {
+ fmt.Printf("target_slice:%v\n", target_slice)
+ }
+ }
+}
+
+func TestDeepClone(t *testing.T) {
+ p1 := NewPlayer(100000000, "Jordan")
+ if p1_map, err := DeepClone(p1); err != nil {
+ t.Errorf("Expected nil, but got err:%s", err)
+ } else {
+ fmt.Printf("p1:%s\n", p1)
+ before := fmt.Sprintf("%v", p1_map)
+ p1.Name = "Jordan Zuo"
+ fmt.Printf("p1:%s\n", p1)
+ after := fmt.Sprintf("%v", p1_map)
+ fmt.Printf("before:%s\n", before)
+ fmt.Printf("after:%s\n", after)
+ if before != after {
+ t.Errorf("Expected before and after same, but got different")
+ }
+ }
+
+ intSlice1 := []int{1, 2, 3, 5}
+ if intSlice2_interface, err := DeepClone(intSlice1); err != nil {
+ t.Errorf("Expected nil, but got err:%s", err)
+ } else {
+ fmt.Printf("intSlice1:%v\n", intSlice1)
+ before := fmt.Sprintf("%v", intSlice2_interface)
+ intSlice1 = append(intSlice1, 10)
+ fmt.Printf("intSlice1:%v\n", intSlice1)
+ after := fmt.Sprintf("%v", intSlice2_interface)
+ fmt.Printf("before:%s\n", before)
+ fmt.Printf("after:%s\n", after)
+ if before != after {
+ t.Errorf("Expected before and after same, but got different")
+ }
+ }
+}
+
+func TestDeepCloneWithNumberType(t *testing.T) {
+ p1 := NewPlayer(100000000, "Jordan")
+ if p1_interface, err := DeepCloneWithNumberType(p1); err != nil {
+ t.Errorf("Expected nil, but got err:%s", err)
+ } else {
+ if p1_map, ok := p1_interface.(map[string]interface{}); !ok {
+ t.Errorf("Expected nil, but got err:%s", err)
+ } else {
+ fmt.Printf("p1:%s\n", p1)
+ before := fmt.Sprintf("%v", p1_map)
+ p1.Name = "Jordan Zuo"
+ fmt.Printf("p1:%s\n", p1)
+ after := fmt.Sprintf("%v", p1_map)
+ fmt.Printf("before:%s\n", before)
+ fmt.Printf("after:%s\n", after)
+ if before != after {
+ t.Errorf("Expected before and after same, but got different")
+ }
+
+ fmt.Printf("p1_interface_map:%v\n", p1_map)
+ id, ok := p1_map["Id"].(json.Number)
+ id_int, err := id.Int64()
+ if !ok || err != nil || id_int != 100000000 {
+ t.Errorf("Expected got 100000000, but got %v, ok:%v, err:%s\n", id_int, ok, err)
+ }
+ }
+ }
+}
+
+type Player struct {
+ Id int
+ Name string
+}
+
+func (player *Player) String() string {
+ return fmt.Sprintf("{Addr:%v, Id:%v, Name:%s}", &player, player.Id, player.Name)
+}
+
+func NewPlayer(id int, name string) *Player {
+ return &Player{
+ Id: id,
+ Name: name,
+ }
+}
diff --git a/.svn/pristine/34/343fd5ed458ab13b56f9ac7761adf383671377ed.svn-base b/.svn/pristine/34/343fd5ed458ab13b56f9ac7761adf383671377ed.svn-base
new file mode 100644
index 0000000..8e52a2b
--- /dev/null
+++ b/.svn/pristine/34/343fd5ed458ab13b56f9ac7761adf383671377ed.svn-base
@@ -0,0 +1,67 @@
+package gameLogMgr
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+ "time"
+
+ "goutil/debugUtil"
+ "goutil/stringUtil"
+ "goutil/timeUtil"
+)
+
+func TestWrite(t *testing.T) {
+ debugUtil.SetDebug(true)
+
+ brokerList := []string{"10.1.0.202:9092", "10.1.0.204:9092", "10.1.0.205:9092"}
+ Start(brokerList, "", "")
+
+ topic := "test2"
+ serverGroupId := int32(20011)
+ for i := 0; i < 5; i++ {
+ Write(topic, serverGroupId, getGameLog(i))
+ }
+
+ time.Sleep(5 * time.Second)
+ Stop()
+}
+
+func BenchmarkWrite(b *testing.B) {
+ debugUtil.SetDebug(true)
+ topic := "test2"
+ serverGroupId := int32(20011)
+
+ brokerList := []string{"10.1.0.202:9092", "10.1.0.204:9092", "10.1.0.205:9092"}
+ Start(brokerList, "", "")
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Write(topic, serverGroupId, getGameLog(i))
+ }
+ b.StopTimer()
+
+ Stop()
+}
+
+func getGameLog(int2 int) string {
+ //kafkaLog组装
+ var buffer bytes.Buffer
+ buffer.WriteString("{")
+ buffer.WriteString(fmt.Sprintf("\"#account_id\":\"%s\"", "123456789123456789"))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"#time\":\"%s\"", time.Now().Format("2006-01-02 15:04:05")))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"#uuid\":\"%s\"", stringUtil.GetNewGUID()))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"#event_id\":\"\""))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"#type\":\"track\""))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"#event_name\":\"achievement_change_log\""))
+ buffer.WriteString(",")
+ buffer.WriteString(fmt.Sprintf("\"properties\":{\"PartnerId\":%d,\"ServerId\":%d,\"Crtime\":\"%s\",\"Crdate\":\"%s\"}", 600021, int2, timeUtil.ToDateTimeString2(time.Now()), timeUtil.ToDateString2(time.Now())))
+ buffer.WriteString("}")
+
+ return buffer.String()
+}
diff --git a/.svn/pristine/34/3449f3eb7da2660d83da36bd4e0b728e917c7f96.svn-base b/.svn/pristine/34/3449f3eb7da2660d83da36bd4e0b728e917c7f96.svn-base
new file mode 100644
index 0000000..eb50995
--- /dev/null
+++ b/.svn/pristine/34/3449f3eb7da2660d83da36bd4e0b728e917c7f96.svn-base
@@ -0,0 +1,231 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/Shopify/sarama v1.29.1/go.mod h1:mdtqvCSg8JOxk8PmpTNGyo6wzd4BMm4QXSfDnTXmgkE=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+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/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
+github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4 h1:OoL469zqSNrTLSz5zeVF/I6VOO7fiw2bzSzQe4J557c=
+github.com/elastic/go-elasticsearch/v8 v8.0.0-20210916085751-c2fb55d91ba4/go.mod h1:xe9a/L2aeOgFKKgrO3ibQTnMdpAeL0GC+5/HpGScSa4=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
+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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
+github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+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/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
+github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
+github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
+github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
+github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
+github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
+github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
+github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
+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.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+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.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
+github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+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/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+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 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.230/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vms v1.0.230/go.mod h1:zElyabRGi8DktckzhT3krsYChstFJdSrzDb7pwF2P58=
+github.com/xdg/scram v1.0.3/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
+golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
+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.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
+gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/.svn/pristine/34/34c4995e93e1d7fb867c6043db15d57863b64727.svn-base b/.svn/pristine/34/34c4995e93e1d7fb867c6043db15d57863b64727.svn-base
new file mode 100644
index 0000000..2539dfb
--- /dev/null
+++ b/.svn/pristine/34/34c4995e93e1d7fb867c6043db15d57863b64727.svn-base
@@ -0,0 +1,47 @@
+package httpSender
+
+import (
+ "errors"
+ "fmt"
+
+ // "goutil/debugUtil"
+ "goutil/webUtil"
+)
+
+// 实现Sender相关接口
+
+type httpClient struct{}
+
+// 发送Requester
+func (this *httpClient) Send(req Requester) (rspn []byte, err error) {
+ if req.GetMethod() == "POST" {
+ rspn, err = this.post(req)
+ return
+ } else {
+ err = errors.New(fmt.Sprintf("request: unsupport method (%s)", req.GetMethod()))
+ return
+ }
+}
+
+// 发送 post 请求
+func (*httpClient) post(req Requester) ([]byte, error) {
+ url := req.GetUrl()
+ bytes := req.GetData()
+
+ // debugUtil.Printf("httpClient-POST %s\r\n%v\n", url, string(bytes))
+
+ rspn, err := webUtil.PostByteData(url, bytes, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ // body := []byte("{\"result\":0,\"errmsg\":\"OK\",\"ext\":\"hello-world\",\"sid\":\"6:59106203271444582828\",\"fee\":1}")
+
+ // debugUtil.Printf("httpClient-Res: %s", string(rspn))
+
+ return rspn, nil
+}
+
+func New() *httpClient {
+ return new(httpClient)
+}
diff --git a/.svn/pristine/34/34cd0a6c1e01175f811d01e6be3886accfb3919f.svn-base b/.svn/pristine/34/34cd0a6c1e01175f811d01e6be3886accfb3919f.svn-base
new file mode 100644
index 0000000..84fe65e
--- /dev/null
+++ b/.svn/pristine/34/34cd0a6c1e01175f811d01e6be3886accfb3919f.svn-base
@@ -0,0 +1,8 @@
+// ************************************
+// @package: client
+// @description: grpc客户端辅助包
+// @author: byron
+// @revision history:
+// @create date: 2022-01-19 16:50:24
+// ************************************
+package client
diff --git a/.svn/pristine/35/3547deaad7e807c519e9f84e8e45315bcb11bee2.svn-base b/.svn/pristine/35/3547deaad7e807c519e9f84e8e45315bcb11bee2.svn-base
new file mode 100644
index 0000000..e388016
--- /dev/null
+++ b/.svn/pristine/35/3547deaad7e807c519e9f84e8e45315bcb11bee2.svn-base
@@ -0,0 +1,63 @@
+package monitorNewMgr
+
+import (
+ "sync"
+ "time"
+
+ "goutil/stringUtil"
+)
+
+const (
+ // CON_MONITOR_HISTORY_SIZE 历史监控信息保存数量
+ CON_MONITOR_HISTORY_SIZE = 3
+
+ // CON_MONITOR_HISTORY_VALID_SECONDS 历史监控信息有效的秒数
+ CON_MONITOR_HISTORY_VALID_SECONDS = 30
+
+ // CON_MONITOR_HISTORY_SIMILARITY_THERSHOLD 历史监控信息相似度的阈值
+ CON_MONITOR_HISTORY_SIMILARITY_THERSHOLD = 0.9
+)
+
+var (
+ monitorHistoryList = make([]*MonitorHistory, 0, CON_MONITOR_HISTORY_SIZE)
+ monitorHistoryMutex sync.Mutex
+)
+
+func checkSimilarity(monitorMessage string, timestamp int64) (valid bool) {
+ //默认监控信息有效
+ valid = true
+
+ monitorHistoryMutex.Lock()
+ defer monitorHistoryMutex.Unlock()
+
+ // 从后往前(按时间从后往前)遍历,以便于可以及时退出
+ for i := len(monitorHistoryList) - 1; i >= 0; i-- {
+ item := monitorHistoryList[i]
+
+ // 如果已经过期,则不用处理; 返回之前的状态即可(当前的已经过期,则之前的也一定已经过期)
+ if time.Now().Unix()-item.Timestamp > CON_MONITOR_HISTORY_VALID_SECONDS {
+ break
+ }
+
+ // 如果两个字符串的长度相差2倍,则无须继续判断,继续与下一条数据进行比较
+ lenA, lenB := len(monitorMessage), len(item.MonitorMessage)
+ if lenA > 2*lenB || lenB > 2*lenA {
+ continue
+ }
+
+ // 判断两个字符串的相似度(如果相似度超过阈值,则此日志无效)
+ _, similarity := stringUtil.Similarity(monitorMessage, item.MonitorMessage)
+ if similarity >= CON_MONITOR_HISTORY_SIMILARITY_THERSHOLD {
+ valid = false
+ return // 直接返回,无需将当前日志添加到历史列表中,以提高性能
+ }
+ }
+
+ // 将消息添加到历史消息列表中
+ monitorHistoryList = append(monitorHistoryList, newMonitorHistory(monitorMessage, timestamp))
+ if len(monitorHistoryList) > CON_MONITOR_HISTORY_SIZE {
+ monitorHistoryList = monitorHistoryList[len(monitorHistoryList)-CON_MONITOR_HISTORY_SIZE:]
+ }
+
+ return
+}
diff --git a/.svn/pristine/35/3566bd2849a9eca9f553cedecc4a9b2ebd621b23.svn-base b/.svn/pristine/35/3566bd2849a9eca9f553cedecc4a9b2ebd621b23.svn-base
new file mode 100644
index 0000000..9963b15
--- /dev/null
+++ b/.svn/pristine/35/3566bd2849a9eca9f553cedecc4a9b2ebd621b23.svn-base
@@ -0,0 +1,36 @@
+package user
+
+import (
+ "common/cache"
+ "common/connection"
+)
+
+func init() {
+ //注册数据库
+ connection.RegisterDBModel(&User{})
+}
+
+type User struct {
+ ID int64 `gorm:"column:id;primary_key;comment:用户id;autoIncrementIncrement" json:"id"`
+ //账号
+ Account string `gorm:"column:account;comment:账号" json:"account"`
+ Name string `gorm:"column:name;comment:用户名称" json:"name"`
+ Password string `gorm:"column:password;comment:用户密码" json:"password"`
+ //性别
+ Sex int32 `gorm:"column:sex;comment:性别" json:"sex"`
+ //生日
+ Birthday string `gorm:"column:birthday;comment:生日" json:"birthday"`
+ //手机
+ Phone int64 `gorm:"column:phone;comment:手机" json:"phone"`
+ //邮箱
+ Email string `gorm:"column:email;comment:邮箱" json:"email"`
+ //备注
+ Describe string `gorm:"column:describe;comment:备注" json:"describe"`
+
+ //玩家的缓存对象
+ Cache *cache.Cache
+}
+
+func (User) TableName() string {
+ return "user"
+}
diff --git a/.svn/pristine/35/357e65a8770e13e0ad7e76c3c6635a87600816b2.svn-base b/.svn/pristine/35/357e65a8770e13e0ad7e76c3c6635a87600816b2.svn-base
new file mode 100644
index 0000000..0b79498
--- /dev/null
+++ b/.svn/pristine/35/357e65a8770e13e0ad7e76c3c6635a87600816b2.svn-base
@@ -0,0 +1,83 @@
+package webServer
+
+import (
+ "common/resultStatus"
+)
+
+// ResponseObject
+// @description: 响应对象
+type ResponseObject struct {
+ // 响应结果的状态值
+ Code resultStatus.StatusCode
+
+ // Status 状态
+ Status int32
+
+ // 响应结果的状态值所对应的描述信息
+ Message string
+
+ // 响应结果的数据
+ Value interface{}
+}
+
+// SetResultStatus
+// @description: 设置响应结果的状态值
+// parameter:
+// @receiver this: this
+// @rs: 响应结果的状态值
+// return:
+// @*ResponseObject: 响应结果对象
+func (this *ResponseObject) SetResultStatus(rs resultStatus.ResultStatus) *ResponseObject {
+ this.Code = rs.Code()
+ this.Message = rs.Message()
+
+ return this
+}
+
+// SetData
+// @description: 设置响应对象数据
+// parameter:
+// @receiver this: this
+// @data: 响应结果的数据
+// return:
+// @*ResponseObject: 响应结果对象
+func (this *ResponseObject) SetData(data interface{}) *ResponseObject {
+ this.Value = data
+ return this
+}
+
+// IsSuccess
+// @description: 是否是请求成功
+// parameter:
+// @receiver this:this
+// return:
+// @bool:是请求成功
+func (this *ResponseObject) IsSuccess() bool {
+ return this.Code == resultStatus.Success.Code()
+}
+
+// SetCodeStatus
+// @description: 同步code和status状态
+// parameter:
+// @receiver this:this
+// return:
+func (this *ResponseObject) SetCodeStatus() {
+ if this.Code == resultStatus.Success.Code() && resultStatus.StatusCode(this.Status) != resultStatus.Success.Code() {
+ this.Code = resultStatus.StatusCode(this.Status)
+ }
+
+ return
+}
+
+// GetInitResponseObj
+// @description: 获取初始的响应对象
+// parameter:
+// return:
+// @*ResponseObject: 响应对象
+func GetInitResponseObj() *ResponseObject {
+ return &ResponseObject{
+ Code: resultStatus.Success.Code(),
+ Message: "",
+ Value: nil,
+ }
+}
diff --git a/.svn/pristine/35/35d65336c7541bc544702d797fcbda5918ed0177.svn-base b/.svn/pristine/35/35d65336c7541bc544702d797fcbda5918ed0177.svn-base
new file mode 100644
index 0000000..9363eea
--- /dev/null
+++ b/.svn/pristine/35/35d65336c7541bc544702d797fcbda5918ed0177.svn-base
@@ -0,0 +1,57 @@
+package managecenterModel
+
+import (
+ . "goutil/mysqlUtil"
+ . "goutil/redisUtil"
+)
+
+// 数据库连接字符串配置
+type DBConnectionConfig struct {
+ // 模型数据库内网连接字符串
+ GameModelDB string
+
+ // 游戏数据库内网连接字符串
+ GameDB string
+
+ // 日志数据库内网连接字符串
+ LogDB string
+
+ // Redis连接字符串
+ RedisConfig string
+}
+
+// 获取游戏模型数据库连接
+// 返回值:
+// 数据库连接配置对象
+// 错误对象
+func (this *DBConnectionConfig) GetGameModelDBConn() (dbConfig *DBConfig, err error) {
+ dbConfig, err = NewDBConfig2(this.GameModelDB)
+ return
+}
+
+// 获取游戏数据库连接
+// 返回值:
+// 数据库连接配置对象
+// 错误对象
+func (this *DBConnectionConfig) GetGameDBConn() (dbConfig *DBConfig, err error) {
+ dbConfig, err = NewDBConfig2(this.GameDB)
+ return
+}
+
+// 获取游戏日志数据库连接
+// 返回值:
+// 数据库连接配置对象
+// 错误对象
+func (this *DBConnectionConfig) GetLogDBConn() (dbConfig *DBConfig, err error) {
+ dbConfig, err = NewDBConfig2(this.LogDB)
+ return
+}
+
+// 获取Redis配置
+// 返回值:
+// redis配置对象
+// 错误对象
+func (this *DBConnectionConfig) GetRedisConfig() (redisConfig *RedisConfig, err error) {
+ redisConfig, err = NewRedisConfig(this.RedisConfig)
+ return
+}
diff --git a/.svn/pristine/36/368ca45601698339d1c23760a5460bde5c1412b5.svn-base b/.svn/pristine/36/368ca45601698339d1c23760a5460bde5c1412b5.svn-base
new file mode 100644
index 0000000..c1ed7b6
--- /dev/null
+++ b/.svn/pristine/36/368ca45601698339d1c23760a5460bde5c1412b5.svn-base
@@ -0,0 +1,221 @@
+/*
+未实现的哈希表方法:
+MOVE、SCAN、SORT、FLUSHDB、FLUSHALL、SELECT、SWAPDB
+*/
+package redisUtil
+
+import (
+ "github.com/gomodule/redigo/redis"
+)
+
+/*
+EXISTS key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+检查给定 key 是否存在。
+
+返回值
+若 key 存在,返回 1 ,否则返回 0 。
+*/
+func (this *RedisPool) Exists(key string) (exist bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ result, err = redis.Int(conn.Do("EXISTS", key))
+ if err != nil {
+ return
+ }
+
+ if result == 1 {
+ exist = true
+ }
+
+ return
+}
+
+/*
+TYPE key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+返回 key 所储存的值的类型。
+
+返回值
+none (key不存在)
+
+string (字符串)
+
+list (列表)
+
+set (集合)
+
+zset (有序集)
+
+hash (哈希表)
+
+stream (流)
+*/
+func (this *RedisPool) Type(key string) (_type string, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ _type, err = redis.String(conn.Do("TYPE", key))
+ return
+}
+
+/*
+RENAME key newkey
+
+将 key 改名为 newkey 。
+
+当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
+
+当 newkey 已经存在时, RENAME 命令将覆盖旧值。
+
+可用版本:
+>= 1.0.0
+时间复杂度:
+O(1)
+返回值:
+改名成功时提示 OK ,失败时候返回一个错误。
+*/
+func (this *RedisPool) Rename(key, newkey string) (err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ _, err = conn.Do("RENAME", key, newkey)
+ return
+}
+
+/*
+RENAMENX key newkey
+
+当且仅当 newkey 不存在时,将 key 改名为 newkey 。
+
+当 key 不存在时,返回一个错误。
+
+可用版本:
+>= 1.0.0
+时间复杂度:
+O(1)
+返回值:
+修改成功时,返回 1 。
+如果 newkey 已经存在,返回 0 。
+*/
+func (this *RedisPool) RenameNX(key, newkey string) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ result, err = redis.Int(conn.Do("RENAMENX", key, newkey))
+ if err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+DEL key [key ...]
+
+删除给定的一个或多个 key 。
+
+不存在的 key 会被忽略。
+
+可用版本:
+>= 1.0.0
+时间复杂度:
+O(N), N 为被删除的 key 的数量。
+删除单个字符串类型的 key ,时间复杂度为O(1)。
+删除单个列表、集合、有序集合或哈希表类型的 key ,时间复杂度为O(M), M 为以上数据结构内的元素数量。
+返回值:
+被删除 key 的数量。
+*/
+func (this *RedisPool) Del(keys ...string) (count int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ count, err = redis.Int(conn.Do("DEL", redis.Args{}.AddFlat(keys)...))
+ return
+}
+
+/*
+从当前数据库中随机返回(不删除)一个 key 。
+
+可用版本:
+>= 1.0.0
+时间复杂度:
+O(1)
+返回值:
+当数据库不为空时,返回一个 key 。
+当数据库为空时,返回 nil 。
+*/
+func (this *RedisPool) RandomKey() (key string, exist bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var reply interface{}
+ reply, err = conn.Do("RANDOMKEY")
+ if err != nil {
+ return
+ }
+ if reply == nil {
+ return
+ }
+
+ key, err = redis.String(reply, err)
+ if err != nil {
+ return
+ }
+
+ exist = true
+ return
+}
+
+/*
+DBSIZE
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+返回当前数据库的 key 的数量。
+
+返回值
+当前数据库的 key 的数量。
+*/
+func (this *RedisPool) DBSize() (keyCount int, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ keyCount, err = redis.Int(conn.Do("DBSIZE"))
+ return
+}
+
+/*
+KEYS pattern
+
+查找所有符合给定模式 pattern 的 key 。
+
+KEYS * 匹配数据库中所有 key 。
+KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
+KEYS h*llo 匹配 hllo 和 heeeeello 等。
+KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
+特殊符号用 \ 隔开
+
+KEYS 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 key ,你最好还是用 Redis 的集合结构(set)来代替。
+可用版本:
+>= 1.0.0
+时间复杂度:
+O(N), N 为数据库中 key 的数量。
+返回值:
+符合给定模式的 key 列表。
+*/
+func (this *RedisPool) Keys(pattern string) (keyList []string, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ keyList, err = redis.Strings(conn.Do("KEYS", pattern))
+ return
+}
diff --git a/.svn/pristine/36/36d0e387eafa0d8f7a60cec4a9b30a2133bcc6bb.svn-base b/.svn/pristine/36/36d0e387eafa0d8f7a60cec4a9b30a2133bcc6bb.svn-base
new file mode 100644
index 0000000..5808105
--- /dev/null
+++ b/.svn/pristine/36/36d0e387eafa0d8f7a60cec4a9b30a2133bcc6bb.svn-base
@@ -0,0 +1,409 @@
+package coroutine_timer
+
+import (
+ "fmt"
+ "math"
+ "time"
+
+ "goutil/logUtil"
+ "goutil/stringUtil"
+)
+
+const (
+ // 启动暂停时间
+ con_STAR_SLEEP_NUM = 3
+
+ // 秒级定时器卡槽数量
+ con_SECOND_SLOT_NUM = 60
+
+ //分钟级定时器卡槽数量
+ con_MINUTES_SLOT_NUM = 60
+)
+
+var (
+ // 秒级定时器下标
+ secIndex = 0
+
+ // 秒级定时器当前开始时间
+ secondStarTime int64
+
+ // 秒级定时器槽
+ secondsTimers [con_SECOND_SLOT_NUM]*timersModel
+
+ // 分钟级定时器下标
+ minIndex = 0
+
+ // 分钟级定时器当前开始时间
+ minStarTime int64
+
+ // 分钟级定时器槽
+ minutesTimers [con_MINUTES_SLOT_NUM]*timersModel
+
+ // 其他定时器存放槽
+ otherTimers *timersModel
+
+ // 操作通道
+ cmdChan chan *cmdModel
+)
+
+func init() {
+ for i := 0; i < con_SECOND_SLOT_NUM; i++ {
+ secondsTimers[i] = newTimersModel()
+ }
+ for i := 0; i < con_MINUTES_SLOT_NUM; i++ {
+ minutesTimers[i] = newTimersModel()
+ }
+
+ otherTimers = newTimersModel()
+ cmdChan = make(chan *cmdModel, 1000)
+ secondStarTime = time.Now().Unix()
+ minStarTime = secondStarTime + con_SECOND_SLOT_NUM
+
+ go chanHandler()
+}
+
+// AddTimer
+// @description: 添加定时回调
+// parameter:
+//
+// @afterSecond:延后多少时间执行
+// @exfun:执行方法
+// @obj:执行传入的参数
+//
+// return:
+//
+// @string:
+func AddTimer(afterSecond int, exfun func(interface{}), obj interface{}) string {
+ tick := time.Now().Unix() + int64(afterSecond)
+ return AddTimer3(tick, exfun, obj)
+}
+
+// AddTimer2
+// @description: 添加定时回调
+// parameter:
+//
+// @t:执行时间点
+// @exfun:执行方法
+// @obj:执行传入的参数
+//
+// return:
+//
+// @string:
+func AddTimer2(t time.Time, exfun func(interface{}), obj interface{}) string {
+ tick := t.Unix()
+ return AddTimer3(tick, exfun, obj)
+}
+
+// AddTimer3
+// @description: 添加定时回调
+// parameter:
+//
+// @tick:执行时间点
+// @exfun:执行方法
+// @obj:执行传入的参数
+//
+// return:
+//
+// @newId:
+func AddTimer3(tick int64, exfun func(interface{}), obj interface{}) (newId string) {
+ newId = stringUtil.GetNewUUID()
+ newObj := newTimerObj(newId, tick, exfun, obj)
+
+ cnm := newCmdModel(cmd_add, newObj)
+ cmdChan <- cnm
+
+ return
+}
+
+// AddTimer4
+// @description: 添加定时回调(此方法会在内部校验id,所以性能会比其他AddTimer方法低)
+// parameter:
+//
+// @id:定时id(外部需要自行保证id唯一)
+// @tick:执行时间点
+// @exfun:执行方法
+// @obj:执行传入的参数
+//
+// return:
+//
+// @err:
+func AddTimer4(id string, tick int64, exfun func(interface{}), obj interface{}) (err error) {
+ newObj := newTimerObj(id, tick, exfun, obj)
+ newObj.needCheckId = true
+
+ // 加入处理队列
+ cnm := newCmdModel(cmd_add, newObj)
+ cmdChan <- cnm
+
+ // 等待处理结束
+ <-cnm.waitChan
+
+ // 返回处理结果
+ err = cnm.err
+
+ return
+}
+
+// DeleteTimer
+// @description: 删除定时器
+// parameter:
+//
+// @id:
+//
+// return:
+func DeleteTimer(id string) {
+ cnm := newCmdModel(cmd_del, id)
+ cmdChan <- cnm
+}
+
+// chanHandler
+// @description: channel处理
+// parameter:
+// return:
+func chanHandler() {
+ defer func() {
+ if err := recover(); err != nil {
+ logUtil.ErrorLog("coroutine-timer.excute err:%s", err)
+ }
+ }()
+
+ // 暂停一下再处理,避免启动立即处理,其他数据还没准备好
+ time.Sleep(con_STAR_SLEEP_NUM * time.Second)
+
+ at := time.After(time.Second * 1)
+ for {
+ select {
+ case cm := <-cmdChan:
+ switch cm.cmd {
+ case cmd_add:
+ cmdAdd(cm)
+ case cmd_del:
+ cmdDel(cm)
+ }
+ case <-at:
+ // byron:需要处理时间后调导致跳时间的问题:调整后应该马上执行的
+
+ // 计算需要执行的次数
+ n := time.Now().Unix() - secondStarTime - int64(secIndex)
+ if n > 0 {
+
+ // 执行对应次数的方法 --- 正常应该只执行1此,调时间后,此处会追时间
+ var i int64
+ for i = 0; i < n; i++ {
+ cmdRun()
+ }
+ }
+
+ at = time.After(time.Second * 1)
+ }
+ }
+}
+
+// cmdAdd
+// @description: 添加定时器
+// parameter:
+//
+// @cm:
+//
+// return:
+func cmdAdd(cm *cmdModel) {
+ newObj := cm.paramObj.(*timerObj)
+ if newObj.needCheckId && checkTimerExist(newObj.id) {
+ cm.err = fmt.Errorf("已经存在id=%s的timer", newObj.id)
+ cm.waitChan <- struct{}{}
+ return
+ }
+
+ // 如果执行时间比当前时间小,则放入最近的调度卡槽,以便尽快执行
+ tick := newObj.tick
+ if tick <= (secondStarTime + int64(secIndex)) {
+ tick = (secondStarTime + int64(secIndex)) + 1
+ }
+
+ // 落在秒钟级别定时器上
+ if tick < (secondStarTime + con_SECOND_SLOT_NUM) {
+ index := (int)(tick - secondStarTime)
+ secondsTimers[index].addTimer(newObj)
+ cm.waitChan <- struct{}{}
+ return
+ }
+
+ // 落在分钟级别定时器上
+ if tick < (minStarTime + con_MINUTES_SLOT_NUM*con_SECOND_SLOT_NUM) {
+ index := (int)(tick-minStarTime) / con_SECOND_SLOT_NUM
+ minutesTimers[index].addTimer(newObj)
+ cm.waitChan <- struct{}{}
+ return
+ }
+
+ //落在小时级别定时器上
+ otherTimers.addTimer(newObj)
+
+ // 返回操作完成
+ cm.waitChan <- struct{}{}
+}
+
+// cmdDel
+// @description: 删除timer
+// parameter:
+//
+// @cm:
+//
+// return:
+func cmdDel(cm *cmdModel) {
+ id := cm.paramObj.(string)
+
+ // 移除秒级别定时器
+ for _, item := range secondsTimers {
+ item.delTimer(id)
+ }
+
+ // 移除分种级定时器
+ for _, item := range minutesTimers {
+ item.delTimer(id)
+ }
+
+ // 移除时钟级定时器
+ otherTimers.delTimer(id)
+
+ // 返回操作完成
+ cm.waitChan <- struct{}{}
+}
+
+// cmdRun
+// @description: 运行定时器
+// parameter:
+// return:
+func cmdRun() {
+ defer func() {
+ if err := recover(); err != nil {
+ logUtil.ErrorLog("coroutine-timer.inExcute err:%s", err)
+ }
+ }()
+
+ // 执行秒级定时器
+ timers := getSencondTimers()
+ if len(timers) == 0 {
+ return
+ }
+
+ for _, t := range timers {
+ go safeRun(t)
+ }
+}
+
+// checkTimerExist
+// @description: 校验timer是否存在
+// parameter:
+//
+// @id:id
+//
+// return:
+//
+// @bool:
+func checkTimerExist(id string) bool {
+ // 秒级别定时器检测
+ for _, item := range secondsTimers {
+ if item.exist(id) {
+ return true
+ }
+ }
+
+ // 分种级定时器检测
+ for _, item := range minutesTimers {
+ if item.exist(id) {
+ return true
+ }
+ }
+
+ // 时钟级定时器检测
+ return otherTimers.exist(id)
+}
+
+// getSencondTimers
+// @description: 获取秒级定时器
+// parameter:
+// return:
+//
+// @result:
+func getSencondTimers() (result []*timerObj) {
+ // 获取对应slot里面的定时对象
+ result = secondsTimers[secIndex].getAllTimers2()
+ secondsTimers[secIndex] = newTimersModel()
+ secIndex++
+
+ // 如果达到最大,则重新填装新的调度对象
+ if secIndex == con_SECOND_SLOT_NUM {
+ secIndex = 0
+ secondStarTime = secondStarTime + con_SECOND_SLOT_NUM
+ minTaskList := getMinutesTasks()
+ for _, t := range minTaskList {
+ index := t.tick - secondStarTime
+ secondsTimers[index].addTimer(t)
+ }
+ }
+
+ return
+}
+
+// getMinutesTasks
+// @description: 获取分钟级定时器
+// parameter:
+// return:
+//
+// @result:
+func getMinutesTasks() (result []*timerObj) {
+ // 获取对应slot里面的定时对象
+ result = minutesTimers[minIndex].getAllTimers2()
+ minutesTimers[minIndex] = newTimersModel()
+ minIndex++
+
+ // 如果达到最大,则重新填装新的调度对象
+ if minIndex == con_MINUTES_SLOT_NUM {
+ reInputMin()
+ }
+
+ return
+}
+
+// reInputMin
+// @description: 重新填入分钟级定时器
+// parameter:
+// return:
+func reInputMin() {
+ minIndex = 0
+ minStarTime = minStarTime + con_MINUTES_SLOT_NUM*con_SECOND_SLOT_NUM
+
+ delMap := make(map[string]struct{})
+ for _, t := range otherTimers.getAllTimers() {
+ index := (t.tick - minStarTime) / con_SECOND_SLOT_NUM
+ if index > math.MaxInt || index >= con_MINUTES_SLOT_NUM {
+ continue
+ }
+ minutesTimers[index].addTimer(t)
+ delMap[t.id] = struct{}{}
+ }
+
+ if len(delMap) > 0 {
+ for k := range delMap {
+ otherTimers.delTimer(k)
+ }
+ }
+}
+
+// safeRun
+// @description: 安全运行定时器回调
+// parameter:
+//
+// @t:
+//
+// return:
+func safeRun(t *timerObj) {
+ defer func() {
+ if err := recover(); err != nil {
+ logUtil.ErrorLog("coroutine-timer.safeRun id:%s err:%s", t.id, err)
+ }
+ }()
+
+ t.excuteAction(t.paramObj)
+}
diff --git a/.svn/pristine/36/36dd2756b063ca1786642aa7e12792c0a26d104c.svn-base b/.svn/pristine/36/36dd2756b063ca1786642aa7e12792c0a26d104c.svn-base
new file mode 100644
index 0000000..a947fe3
--- /dev/null
+++ b/.svn/pristine/36/36dd2756b063ca1786642aa7e12792c0a26d104c.svn-base
@@ -0,0 +1,16 @@
+#配置项说明
+log.es.enable=false #(false,默认值,关闭es日志记录,后续配置可不填写; true 打开日志记录)
+log.es.url= #(es服务地址)
+log.es.indexName=1 #(es服务中Index名)
+log.es.level=info #(debug|info|warn|error|fatal等级,等于或高于配置项则记录)
+
+log.file.enable=false #(默认false)
+log.file.path=log #(运行目录下log目录,默认logs)
+log.file.pre=log #(文件名前缀,默认log)
+log.file.enableHour=true #(文件以小时划分,格式:yyyyMMddHH,默认true,false 一天一个文件,格式:yyyyMMdd)
+log.file.level=info
+
+log.console.enable=false #(默认false)
+log.console.level=info
+
+modelcenter.modelDBConnStr=root:moqikaka3306@tcp(10.255.0.10:3306)/xj_model_mr?charset=utf8&parseTime=true&loc=Local&timeout=60s||MaxOpenConns=10||MaxIdleConns=5 #(model数据库信息)
\ No newline at end of file
diff --git a/.svn/pristine/37/370a9eae2ee1aaaeff3dcc4e23bb2a1391220586.svn-base b/.svn/pristine/37/370a9eae2ee1aaaeff3dcc4e23bb2a1391220586.svn-base
new file mode 100644
index 0000000..0fcaa33
--- /dev/null
+++ b/.svn/pristine/37/370a9eae2ee1aaaeff3dcc4e23bb2a1391220586.svn-base
@@ -0,0 +1,19 @@
+package voicemsgMgr
+
+//语音配置参数
+type VoiceMessageConfig struct {
+ //API密钥Id
+ SecretId string
+
+ //API密钥key
+ SecretKey string
+
+ //地域
+ Region string
+
+ //模板ID
+ TemplateId string
+
+ //应用后生成的实际SdkAppid
+ VoiceSdkAppid string
+}
diff --git a/.svn/pristine/37/374dfacb825adc910983b41ee6e2df86611ca117.svn-base b/.svn/pristine/37/374dfacb825adc910983b41ee6e2df86611ca117.svn-base
new file mode 100644
index 0000000..bd36802
--- /dev/null
+++ b/.svn/pristine/37/374dfacb825adc910983b41ee6e2df86611ca117.svn-base
@@ -0,0 +1,193 @@
+package mailUtil
+
+import (
+ "bytes"
+ "crypto/tls"
+ "encoding/base64"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/mail"
+ "net/smtp"
+ "path/filepath"
+ "strings"
+)
+
+// SMTPClient实现
+type simpleClient struct {
+ host string
+ port int
+ isSSL bool
+
+ senderName string
+ senderAddr string
+ senderPwd string
+}
+
+// 返回一个simpleClient作为SMTPClient接口
+func SimpleSMTPClient(_host string, _port int, _isSSL bool,
+ name, address, password string) SMTPClient {
+
+ return &simpleClient{
+ host: _host,
+ port: _port,
+ isSSL: _isSSL,
+
+ senderName: name,
+ senderAddr: address,
+ senderPwd: password,
+ }
+}
+
+func (this *simpleClient) SetServer(_host string, _port int, _isSSL bool) {
+ this.host = _host
+ this.port = _port
+ this.isSSL = _isSSL
+}
+
+func (this *simpleClient) SetSender(name, address, password string) {
+ this.senderName = name
+ this.senderAddr = address
+ this.senderPwd = password
+}
+
+//发送邮件:
+// mailTo 接收方列表
+// subject 主题
+// body 正文
+// isHtmlBody 正文是否html格式
+// attachFiles 附件
+func (this *simpleClient) SendMail(
+ mailTo []string,
+ subject, body string, isHtmlBody bool,
+ attachFiles []string) (err error) {
+
+ defer func() {
+ if r := recover(); r != nil {
+ err = r.(error)
+ }
+ }()
+
+ // 创建连接
+ var conn net.Conn
+
+ if this.isSSL {
+ // TLS config
+ tlsconfig := &tls.Config{
+ InsecureSkipVerify: true,
+ ServerName: this.host,
+ }
+ conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", this.host, this.port), tlsconfig)
+ } else {
+ conn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", this.host, this.port))
+ }
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ // 创建smtp.Client
+ c, err := smtp.NewClient(conn, this.host)
+ if err != nil {
+ return err
+ }
+
+ // 验证信息
+ auth := smtp.PlainAuth("", this.senderAddr, this.senderPwd, this.host)
+ if err = c.Auth(auth); err != nil {
+ return err
+ }
+
+ // 发送方
+ from := mail.Address{this.senderName, this.senderAddr}
+ // 接收方
+ to := make([]string, 0, len(mailTo))
+ for _, v := range mailTo {
+ to = append(to, "<"+v+">")
+ }
+
+ // To && From
+ if err = c.Mail(from.Address); err != nil {
+ return err
+ }
+
+ for _, v := range mailTo {
+ if err = c.Rcpt(v); err != nil {
+ return err
+ }
+ }
+
+ // 边界
+ boundary := "a40acf3c8b7200fc6b04c2f1b3da"
+
+ buff := bytes.NewBuffer(nil)
+
+ // 写入基本信息
+ buff.WriteString(fmt.Sprintf("From: %s\r\n", from.String()))
+ buff.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(to, ", ")))
+ buff.WriteString(fmt.Sprintf("Subject: %s\r\n", subject))
+
+ // 写入邮件头部信息
+ if len(attachFiles) > 0 {
+ buff.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\r\n", boundary))
+
+ // 写入正文的边界信息
+ buff.WriteString(fmt.Sprintf("\r\n--%s\r\n", boundary))
+ }
+
+ // 写入正文头部
+ if isHtmlBody {
+ buff.WriteString(fmt.Sprintf("Content-Type: text/html; charset=\"utf-8\"\r\n"))
+ } else {
+ buff.WriteString(fmt.Sprintf("Content-Type: text/plain; charset=\"utf-8\"\r\n"))
+ }
+ buff.WriteString("\r\n")
+ // 写入正文内容
+ buff.WriteString(body)
+
+ if len(attachFiles) > 0 {
+ for _, file := range attachFiles {
+ fileBytes, err := ioutil.ReadFile(file)
+ if err != nil {
+ return err
+ }
+
+ _, fileName := filepath.Split(file)
+
+ // 写入文件信息
+ buff.WriteString(fmt.Sprintf("\r\n\r\n--%s\r\n", boundary))
+ buff.WriteString("Content-Type: application/octet-stream\r\n")
+ buff.WriteString("Content-Transfer-Encoding: base64\r\n")
+ buff.WriteString(fmt.Sprintf("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n", fileName))
+
+ // 写入文件数据
+ b := make([]byte, base64.StdEncoding.EncodedLen(len(fileBytes)))
+ base64.StdEncoding.Encode(b, fileBytes)
+ buff.Write(b)
+ }
+
+ // 写入结束标识
+ buff.WriteString(fmt.Sprintf("\r\n--%s--", boundary))
+ }
+
+ // Data
+ w, err := c.Data()
+ if err != nil {
+ return err
+ }
+
+ // 写入邮件数据
+ _, err = w.Write(buff.Bytes())
+ if err != nil {
+ return err
+ }
+
+ err = w.Close()
+ if err != nil {
+ return err
+ }
+
+ c.Quit()
+
+ return nil
+}
diff --git a/.svn/pristine/37/37b917300c968fc5f809e08ddcf2abcc2774fd2b.svn-base b/.svn/pristine/37/37b917300c968fc5f809e08ddcf2abcc2774fd2b.svn-base
new file mode 100644
index 0000000..1de6919
--- /dev/null
+++ b/.svn/pristine/37/37b917300c968fc5f809e08ddcf2abcc2774fd2b.svn-base
@@ -0,0 +1,186 @@
+package xmlUtil
+
+import (
+ "strings"
+ "testing"
+)
+
+func findNode(root *Node, name string) *Node {
+ node := root.FirstChild
+ for {
+ if node == nil || node.NodeName == name {
+ break
+ }
+ node = node.NextSibling
+ }
+ return node
+}
+
+func childNodes(root *Node, name string) []*Node {
+ var list []*Node
+ node := root.FirstChild
+ for {
+ if node == nil {
+ break
+ }
+ if node.NodeName == name {
+ list = append(list, node)
+ }
+ node = node.NextSibling
+ }
+ return list
+}
+
+func testNode(t *testing.T, n *Node, expected string) {
+ if n.NodeName != expected {
+ t.Fatalf("expected node name is %s,but got %s", expected, n.NodeName)
+ }
+}
+
+func testAttr(t *testing.T, n *Node, name, expected string) {
+ for _, attr := range n.Attr {
+ if attr.Name.Local == name && attr.Value == expected {
+ return
+ }
+ }
+ t.Fatalf("not found attribute %s in the node %s", name, n.NodeName)
+}
+
+func testValue(t *testing.T, val, expected string) {
+ if val != expected {
+ t.Fatalf("expected value is %s,but got %s", expected, val)
+ }
+}
+
+func TestParse(t *testing.T) {
+ s := `
+
+
+ Harry Potter
+ 29.99
+
+
+ Learning XML
+ 39.95
+
+`
+ root, err := LoadFromReader(strings.NewReader(s))
+ if err != nil {
+ t.Error(err)
+ }
+ if root.Type != DocumentNode {
+ t.Fatal("top node of tree is not DocumentNode")
+ }
+
+ declarNode := root.FirstChild
+ if declarNode.Type != DeclarationNode {
+ t.Fatal("first child node of tree is not DeclarationNode")
+ }
+
+ if declarNode.Attr[0].Name.Local != "version" && declarNode.Attr[0].Value != "1.0" {
+ t.Fatal("version attribute not expected")
+ }
+
+ bookstore := root.LastChild
+ if bookstore.NodeName != "bookstore" {
+ t.Fatal("bookstore elem not found")
+ }
+ if bookstore.FirstChild.NodeName != "\n" {
+ t.Fatal("first child node of bookstore is not empty node(\n)")
+ }
+ books := childNodes(bookstore, "book")
+ if len(books) != 2 {
+ t.Fatalf("expected book element count is 2, but got %d", len(books))
+ }
+ // first book element
+ testNode(t, findNode(books[0], "title"), "title")
+ testAttr(t, findNode(books[0], "title"), "lang", "en")
+ testValue(t, findNode(books[0], "price").InnerText(), "29.99")
+ testValue(t, findNode(books[0], "title").InnerText(), "Harry Potter")
+
+ // second book element
+ testNode(t, findNode(books[1], "title"), "title")
+ testAttr(t, findNode(books[1], "title"), "lang", "en")
+ testValue(t, findNode(books[1], "price").InnerText(), "39.95")
+
+ testValue(t, books[0].OutputXML(), `Harry Potter29.99`)
+}
+
+func TestTooNested(t *testing.T) {
+ s := `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ root, err := LoadFromReader(strings.NewReader(s))
+ if err != nil {
+ t.Error(err)
+ }
+ aaa := findNode(root, "AAA")
+ if aaa == nil {
+ t.Fatal("AAA node not exists")
+ }
+ ccc := aaa.LastChild
+ if ccc.NodeName != "CCC" {
+ t.Fatalf("expected node is CCC,but got %s", ccc.NodeName)
+ }
+ bbb := ccc.PrevSibling
+ if bbb.NodeName != "BBB" {
+ t.Fatalf("expected node is bbb,but got %s", bbb.NodeName)
+ }
+ ddd := findNode(bbb, "DDD")
+ testNode(t, ddd, "DDD")
+ testNode(t, ddd.LastChild, "CCC")
+}
+
+func TestSelectElement(t *testing.T) {
+ s := `
+
+
+
+
+
+
+
+
+ `
+ root, err := LoadFromReader(strings.NewReader(s))
+ if err != nil {
+ t.Error(err)
+ }
+ version, _ := root.FirstChild.SelectAttr("version")
+ if version != "1.0" {
+ t.Fatal("version!=1.0")
+ }
+ aaa := findNode(root, "AAA")
+ var n *Node
+ n = aaa.SelectElement("BBB")
+ if n == nil {
+ t.Fatalf("n is nil")
+ }
+ n = aaa.SelectElement("CCC")
+ if n == nil {
+ t.Fatalf("n is nil")
+ }
+
+ var ns []*Node
+ ns = aaa.SelectElements("CCC")
+ if len(ns) != 2 {
+ t.Fatalf("len(ns)!=2")
+ }
+}
diff --git a/.svn/pristine/37/37be33c1543987b2fc1e5ad1e0041ffbbef1231f.svn-base b/.svn/pristine/37/37be33c1543987b2fc1e5ad1e0041ffbbef1231f.svn-base
new file mode 100644
index 0000000..cd7f37e
--- /dev/null
+++ b/.svn/pristine/37/37be33c1543987b2fc1e5ad1e0041ffbbef1231f.svn-base
@@ -0,0 +1,6 @@
+package reloadMgr
+
+// 重新加载包,提供重新加载的功能
+// 使用方法:
+// 1、先调用RegisterReloadFunc方法,将重新加载时需要调用的方法进行注册。
+// 2、在需要重新加载时调用Reload()方法
diff --git a/.svn/pristine/37/37e94747cff7c5629f6a5f38855e9ad2891bca8e.svn-base b/.svn/pristine/37/37e94747cff7c5629f6a5f38855e9ad2891bca8e.svn-base
new file mode 100644
index 0000000..9b8a118
--- /dev/null
+++ b/.svn/pristine/37/37e94747cff7c5629f6a5f38855e9ad2891bca8e.svn-base
@@ -0,0 +1,208 @@
+package ensureSendUtil
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+ "sync"
+ "time"
+
+ "goutil/intAndBytesUtil"
+ "goutil/logUtil"
+)
+
+var (
+ errConnectEmpty = fmt.Errorf("scoket reconnecting...")
+ byterOrder = binary.LittleEndian
+)
+
+// 实现 EnsureSender和sender接口
+type tcpSender struct {
+ // 需要实现的接口
+ EnsureSender
+
+ // 包含sender接口部分实现
+ *baseSender
+
+ // 数据目录
+ dataFolder string
+
+ // 服务器地址
+ address string
+
+ // 连接
+ conn net.Conn
+
+ // 用于重连时互斥
+ mutex sync.Mutex
+
+ // 用于sendLoop和resendLoop发送退出信号
+ closeSignal chan struct{}
+}
+
+// 创建一个tcp数据发送器
+// 参数:
+//
+// _dataFolder 数据存放目录
+// _address 连接地址
+func NewTCPSender(_dataFolder, _address string) (EnsureSender, error) {
+ // 连接服务器
+ conn, err := net.DialTimeout("tcp", _address, 5*time.Second)
+ if err != nil {
+ return nil, err
+ }
+
+ this := &tcpSender{
+ dataFolder: _dataFolder,
+ baseSender: newBaseSender(),
+ address: _address,
+ conn: conn,
+ closeSignal: make(chan struct{}),
+ }
+
+ // 新开协程发送数据
+ go sendLoop(this, this.closeSignal)
+
+ // 定时重发
+ go resendLoop(this, _dataFolder, this.closeSignal)
+
+ // 发送心跳包
+ go this.heartBeat()
+
+ return this, nil
+}
+
+// 每隔15秒发送心跳包
+func (this *tcpSender) heartBeat() {
+ defer func() {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+ }
+ }()
+
+ tick := time.Tick(time.Second * 15)
+
+ for {
+ select {
+ case <-this.Done():
+ return
+ case <-tick:
+ this.sendBytes([]byte{})
+ }
+ }
+}
+
+// EnsureSender接口
+// Write:写入数据
+func (this *tcpSender) Write(data string) error {
+ item, err := newTCPDataItem(data)
+ if err != nil {
+ return err
+ }
+
+ this.waitingDataChan <- item
+
+ return nil
+}
+
+// EnsureSender接口
+// Close:关闭
+func (this *tcpSender) Close() error {
+ close(this.done)
+
+ // 关闭socket连接
+ conn := this.conn
+ if conn != nil {
+ conn.Close()
+ }
+
+ // 等待sendLoop和resendLoop退出
+ <-this.closeSignal
+ <-this.closeSignal
+
+ // 保存数据
+ _, e1 := saveData(this.Cache(), this.dataFolder)
+ _, e2 := saveData(this.Data(), this.dataFolder)
+
+ if e2 != nil {
+ if e1 != nil {
+ return fmt.Errorf("%s %s", e1, e2)
+ }
+ return e2
+ } else {
+ return e1
+ }
+}
+
+// Sender接口
+// Send:发送dataItem
+func (this *tcpSender) Send(item dataItem) error {
+ err := this.sendBytes(item.Bytes())
+ if err != nil && err != errConnectEmpty {
+ // 发送失败时发送次数+1
+ item.SetCount(item.Count() + 1)
+ }
+
+ return err
+}
+
+// 发送字节数据
+// 发送格式:[lenght+data]
+func (this *tcpSender) sendBytes(data []byte) error {
+ conn := this.conn
+ if conn == nil {
+ return errConnectEmpty
+ }
+
+ // 将长度转化为字节数组
+ header := intAndBytesUtil.Int32ToBytes(int32(len(data)), byterOrder)
+
+ if len(data) > 0 {
+ data = append(header, data...)
+ } else {
+ data = header
+ }
+
+ _, err := conn.Write(data)
+ if err != nil {
+ this.mutex.Lock()
+ // 发送失败
+ // 检查失败的conn是否this.conn(避免多个线程失败后均调用reconnect)
+ // 是则关闭并重连
+ if conn == this.conn {
+ this.conn.Close()
+ this.conn = nil
+ this.mutex.Unlock()
+
+ // 重连
+ go this.reconnect()
+ } else {
+ this.mutex.Unlock()
+ }
+ }
+
+ return err
+}
+
+// 重连服务器
+func (this *tcpSender) reconnect() error {
+ // lock-it
+ this.mutex.Lock()
+ defer this.mutex.Unlock()
+
+ for {
+ // 检查是否已经重连
+ if this.conn != nil {
+ return nil
+ }
+
+ conn, err := net.DialTimeout("tcp", this.address, 5*time.Second)
+ if err != nil {
+ // 连接失败,5秒后重试
+ <-time.After(time.Second * 5)
+ continue
+ }
+
+ this.conn = conn
+ }
+}
diff --git a/.svn/pristine/37/37fdb38c232c02a13b29a2b8ea947d48e87e0798.svn-base b/.svn/pristine/37/37fdb38c232c02a13b29a2b8ea947d48e87e0798.svn-base
new file mode 100644
index 0000000..74e0625
--- /dev/null
+++ b/.svn/pristine/37/37fdb38c232c02a13b29a2b8ea947d48e87e0798.svn-base
@@ -0,0 +1,54 @@
+提供游戏内的实时排行榜功能,建议最大长度设定<=200
+使用方式:
+
+```go
+package main
+
+import (
+ rank_util "goutil/rank-util"
+)
+
+func main() {
+ // 构造对象
+ r := rank_util.NewRankUtil(20, compar)
+
+ // 刷新排行榜
+ m := &rmodel{k: "byrontest", Fap: 110}
+ ifChangeRank, dm := r.Refresh(m.k, m, true)
+
+ // 获取全部排行榜
+ tempList := r.GetAll()
+
+ // 删除某个key
+ isok := r.Delete("byrontest")
+}
+
+// compar
+// @description: 判断对象大小,返回含义 -1:ab
+// parameter:
+// @a:对象a
+// @b:对象b
+// return:
+// @int:
+func compar(a, b interface{}) int {
+ af := a.(*rmodel).Fap
+ bf := b.(*rmodel).Fap
+ if af > bf {
+ return 1
+ } else if af == bf {
+ return 0
+ } else {
+ return -1
+ }
+}
+
+type rmodel struct {
+ k string
+ Fap int
+}
+
+```
+
+
+
+
diff --git a/.svn/pristine/38/384faa85c664eb83dc8772b69254ad4263c18541.svn-base b/.svn/pristine/38/384faa85c664eb83dc8772b69254ad4263c18541.svn-base
new file mode 100644
index 0000000..712fe6a
--- /dev/null
+++ b/.svn/pristine/38/384faa85c664eb83dc8772b69254ad4263c18541.svn-base
@@ -0,0 +1,259 @@
+package stringUtil
+
+import (
+ "testing"
+)
+
+func TestStringToMap_String_String(t *testing.T) {
+ str := ""
+ seps := []string{",", "|"}
+ data, err := StringToMap_String_String(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3"
+ data, err = StringToMap_String_String(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,5"
+ data, err = StringToMap_String_String(str, seps)
+ if err != nil {
+ t.Errorf("Expected to get no error. But now there is one:%v.", err)
+ return
+ }
+
+ expected := make(map[string]string, 2)
+ expected["1"] = "2"
+ expected["3"] = "5"
+
+ if len(expected) != len(data) {
+ t.Errorf("The length of expected:%d is not equals to length of data:%d", len(expected), len(data))
+ return
+ }
+
+ for k, v := range data {
+ if v1, exists := expected[k]; !exists {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ } else if v != v1 {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ }
+ }
+}
+
+func TestStringToMap_String_Int(t *testing.T) {
+ str := ""
+ seps := []string{",", "|"}
+ data, err := StringToMap_String_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3"
+ data, err = StringToMap_String_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,abc"
+ data, err = StringToMap_String_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,5"
+ data, err = StringToMap_String_Int(str, seps)
+ if err != nil {
+ t.Errorf("Expected to get no error. But now there is one:%v.", err)
+ return
+ }
+
+ expected := make(map[string]int, 2)
+ expected["1"] = 2
+ expected["3"] = 5
+
+ if len(expected) != len(data) {
+ t.Errorf("The length of expected:%d is not equals to length of data:%d", len(expected), len(data))
+ return
+ }
+
+ for k, v := range data {
+ if v1, exists := expected[k]; !exists {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ } else if v != v1 {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ }
+ }
+}
+
+func TestStringToMap_Int_Int(t *testing.T) {
+ str := ""
+ seps := []string{",", "|"}
+ data, err := StringToMap_Int_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3"
+ data, err = StringToMap_Int_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,abc"
+ data, err = StringToMap_Int_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|a,3"
+ data, err = StringToMap_Int_Int(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,5"
+ data, err = StringToMap_Int_Int(str, seps)
+ if err != nil {
+ t.Errorf("Expected to get no error. But now there is one:%v.", err)
+ return
+ }
+
+ expected := make(map[int]int, 2)
+ expected[1] = 2
+ expected[3] = 5
+
+ if len(expected) != len(data) {
+ t.Errorf("The length of expected:%d is not equals to length of data:%d", len(expected), len(data))
+ return
+ }
+
+ for k, v := range data {
+ if v1, exists := expected[k]; !exists {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ } else if v != v1 {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ }
+ }
+}
+
+func TestStringToMap_Int32_Int32(t *testing.T) {
+ str := ""
+ seps := []string{",", "|"}
+ data, err := StringToMap_Int32_Int32(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3"
+ data, err = StringToMap_Int32_Int32(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,abc"
+ data, err = StringToMap_Int32_Int32(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|a,3"
+ data, err = StringToMap_Int32_Int32(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,5"
+ data, err = StringToMap_Int32_Int32(str, seps)
+ if err != nil {
+ t.Errorf("Expected to get no error. But now there is one:%v.", err)
+ return
+ }
+
+ expected := make(map[int32]int32, 2)
+ expected[1] = 2
+ expected[3] = 5
+
+ if len(expected) != len(data) {
+ t.Errorf("The length of expected:%d is not equals to length of data:%d", len(expected), len(data))
+ return
+ }
+
+ for k, v := range data {
+ if v1, exists := expected[k]; !exists {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ } else if v != v1 {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ }
+ }
+}
+
+func TestStringToMap_Int32_Int64(t *testing.T) {
+ str := ""
+ seps := []string{",", "|"}
+ data, err := StringToMap_Int32_Int64(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3"
+ data, err = StringToMap_Int32_Int64(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|3,abc"
+ data, err = StringToMap_Int32_Int64(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,2|a,3"
+ data, err = StringToMap_Int32_Int64(str, seps)
+ if err == nil {
+ t.Errorf("Expected to get an error. But now there isn't.")
+ return
+ }
+
+ str = "1,36524569852|3,365245698521"
+ data, err = StringToMap_Int32_Int64(str, seps)
+ if err != nil {
+ t.Errorf("Expected to get no error. But now there is one:%v.", err)
+ return
+ }
+
+ expected := make(map[int32]int64, 2)
+ expected[1] = 36524569852
+ expected[3] = 365245698521
+
+ if len(expected) != len(data) {
+ t.Errorf("The length of expected:%d is not equals to length of data:%d", len(expected), len(data))
+ return
+ }
+
+ for k, v := range data {
+ if v1, exists := expected[k]; !exists {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ } else if v != v1 {
+ t.Errorf("data is not equals to expected. %v, %v", expected, data)
+ }
+ }
+}
diff --git a/.svn/pristine/39/39a09255683add574e0b3b1b5c7e521de4a47ad3.svn-base b/.svn/pristine/39/39a09255683add574e0b3b1b5c7e521de4a47ad3.svn-base
new file mode 100644
index 0000000..62f5371
--- /dev/null
+++ b/.svn/pristine/39/39a09255683add574e0b3b1b5c7e521de4a47ad3.svn-base
@@ -0,0 +1,100 @@
+// ************************************
+// @package: websocketServer
+// @description: websocket服务端
+// @author:
+// @revision history:
+// @create date: 2022-02-15 14:10:51
+// ************************************
+package websocketServer
+
+import (
+ "github.com/gorilla/websocket"
+ webServer "Framework/webServer"
+ "time"
+)
+
+type WsServer struct {
+ *webServer.HttpServer
+
+ // websocket连接管理
+ *connManager
+}
+
+// RegisterWebsocketHandler
+// @description: 注册websocket回调
+// parameter:
+//
+// @receiver ws:
+// @path:注册的访问路径
+// @handlerFuncObj:回调方法
+// @configObj:Handler配置对象
+//
+// return:
+func (ws *WsServer) RegisterWebsocketHandler(path string, eventCallback *EventCallbackFuncs, configObj *webServer.HandlerConfig) {
+ ws.RegisterHandlerWithUserData(path, hookHandler, configObj, &userDatas{
+ server: ws,
+ eventCallback: eventCallback,
+ })
+}
+
+// RegisterRegexWebsocketHandler
+// @description: 注册正则websocket回调
+// parameter:
+//
+// @receiver wss:
+// @path:注册的正则访问路径
+// @eventCallback:回调方法
+// @configObj:Handler配置对象
+//
+// return:
+func (ws *WsServer) RegisterRegexWebsocketHandler(path string, eventCallback *EventCallbackFuncs, configObj *webServer.HandlerConfig) {
+ ws.RegisterRegexHandlerWithUserData(path, hookHandler, configObj, &userDatas{
+ server: ws,
+ eventCallback: eventCallback,
+ })
+}
+
+func NewWsServer(addr string, isCheckIP bool) (server *WsServer) {
+ server = &WsServer{
+ HttpServer: webServer.NewHttpServer(addr, isCheckIP),
+ connManager: &connManager{
+ upgrader: &websocket.Upgrader{},
+ allConns: make(map[*websocket.Conn]*Context),
+ },
+ }
+
+ // 开启心跳检测协程
+ server.connManager.heartbeatDetect()
+
+ return
+}
+
+func NewWsServer2(addr string, webServerObj webServer.IWebServer) (server *WsServer) {
+ server = &WsServer{
+ HttpServer: webServer.NewHttpServer2(addr, webServerObj),
+ connManager: &connManager{
+ upgrader: &websocket.Upgrader{},
+ allConns: make(map[*websocket.Conn]*Context),
+ },
+ }
+
+ // 开启心跳检测协程
+ server.connManager.heartbeatDetect()
+
+ return
+}
+
+func NewWsServer3(addr string, isCheckIP bool, readTimeout time.Duration, readHeaderTimeout time.Duration, writeTimeout time.Duration) (server *WsServer) {
+ server = &WsServer{
+ HttpServer: webServer.NewHttpServer3(addr, isCheckIP, readTimeout, readHeaderTimeout, writeTimeout),
+ connManager: &connManager{
+ upgrader: &websocket.Upgrader{},
+ allConns: make(map[*websocket.Conn]*Context),
+ },
+ }
+
+ // 开启心跳检测协程
+ server.connManager.heartbeatDetect()
+
+ return
+}
diff --git a/.svn/pristine/3a/3aea22b2166c4d38707ec9cc9c910dd1e4ff2dd8.svn-base b/.svn/pristine/3a/3aea22b2166c4d38707ec9cc9c910dd1e4ff2dd8.svn-base
new file mode 100644
index 0000000..8ff61f4
--- /dev/null
+++ b/.svn/pristine/3a/3aea22b2166c4d38707ec9cc9c910dd1e4ff2dd8.svn-base
@@ -0,0 +1,267 @@
+package mathUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestIsContinuous_byte(t *testing.T) {
+ list := make([]byte, 0, 8)
+ if IsContinuous_byte(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 1)
+ if IsContinuous_byte(list) == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 2)
+ list = append(list, 3)
+ list = append(list, 4)
+ list = append(list, 5)
+ if IsContinuous_byte(list) == false {
+ t.Errorf("it's should be true, but now false-------3")
+ }
+
+ list = append(list, 10)
+ if IsContinuous_byte(list) == true {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+}
+
+func TestIsContinuous_int(t *testing.T) {
+ list := make([]int, 0, 8)
+ if IsContinuous_int(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 11)
+ if IsContinuous_int(list) == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 12)
+ list = append(list, 13)
+ list = append(list, 14)
+ list = append(list, 15)
+ if IsContinuous_int(list) == false {
+ t.Errorf("it's should be true, but now false-------3")
+ }
+
+ list = append(list, 10)
+ if IsContinuous_int(list) == true {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+}
+
+func TestIsContinuous_int32(t *testing.T) {
+ list := make([]int32, 0, 8)
+ if IsContinuous_int32(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 1)
+ if IsContinuous_int32(list) == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 2)
+ list = append(list, 3)
+ list = append(list, 4)
+ list = append(list, 5)
+ if IsContinuous_int32(list) == false {
+ t.Errorf("it's should be true, but now false-------3")
+ }
+
+ list = append(list, 10)
+ if IsContinuous_int32(list) == true {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+}
+
+func TestIsContinuous_int64(t *testing.T) {
+ list := make([]int64, 0, 8)
+ if IsContinuous_int64(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 1)
+ if IsContinuous_int64(list) == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 2)
+ list = append(list, 3)
+ list = append(list, 4)
+ list = append(list, 5)
+ if IsContinuous_int64(list) == false {
+ t.Errorf("it's should be true, but now false-------3")
+ }
+
+ list = append(list, 10)
+ if IsContinuous_int64(list) == true {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+}
+
+func TestIsContinuous_Region(t *testing.T) {
+ list := make([]*IntRegion, 0, 8)
+ if IsContinuous_Region(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, NewIntRegion(101, 110))
+ if IsContinuous_Region(list) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, NewIntRegion(1, 10))
+ if IsContinuous_Region(list) == true {
+ t.Errorf("it's should be false, but now true-------2")
+ }
+
+ list = append(list, NewIntRegion(11, 100))
+ if IsContinuous_Region(list) == false {
+ t.Errorf("it's should be true, but now false-------3")
+ }
+
+}
+
+func TestIsOddFullConvered(t *testing.T) {
+ list := make([]*IntRegion, 0, 8)
+ min, max := 1, 100
+ if IsOddFullConvered(list, min, max) {
+ t.Errorf("it's should be false, but now true-------1")
+ }
+
+ list = append(list, NewIntRegion(1, 10))
+ if IsOddFullConvered(list, min, max) == true {
+ t.Errorf("it's should be false, but now true-------2")
+ }
+
+ list = append(list, NewIntRegion(11, 100))
+ if IsOddFullConvered(list, min, max) == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+}
+
+func TestIsDistinct_byte(t *testing.T) {
+ list := make([]byte, 0, 8)
+ result := IsDistinct_byte(list)
+ fmt.Printf("list:%v,result:%v-------1\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_byte(list)
+ fmt.Printf("list:%v,result:%v-------2\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_byte(list)
+ fmt.Printf("list:%v,result:%v-------3\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+
+ list = append(list, 0)
+ result = IsDistinct_byte(list)
+ fmt.Printf("list:%v,result:%v-------4\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------4")
+ }
+}
+
+func TestIsDistinct_int(t *testing.T) {
+ list := make([]int, 0, 8)
+ result := IsDistinct_int(list)
+ fmt.Printf("list:%v,result:%v-------1\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int(list)
+ fmt.Printf("list:%v,result:%v-------2\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int(list)
+ fmt.Printf("list:%v,result:%v-------3\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+
+ list = append(list, 0)
+ result = IsDistinct_int(list)
+ fmt.Printf("list:%v,result:%v-------4\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------4")
+ }
+}
+
+func TestIsDistinct_int32(t *testing.T) {
+ list := make([]int32, 0, 8)
+ result := IsDistinct_int32(list)
+ fmt.Printf("list:%v,result:%v-------1\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int32(list)
+ fmt.Printf("list:%v,result:%v-------2\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int32(list)
+ fmt.Printf("list:%v,result:%v-------3\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+
+ list = append(list, 0)
+ result = IsDistinct_int32(list)
+ fmt.Printf("list:%v,result:%v-------4\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------4")
+ }
+}
+
+func TestIsDistinct_int64(t *testing.T) {
+ list := make([]int64, 0, 8)
+ result := IsDistinct_int64(list)
+ fmt.Printf("list:%v,result:%v-------1\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------1")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int64(list)
+ fmt.Printf("list:%v,result:%v-------2\n", list, result)
+ if result == false {
+ t.Errorf("it's should be true, but now false-------2")
+ }
+
+ list = append(list, 10)
+ result = IsDistinct_int64(list)
+ fmt.Printf("list:%v,result:%v-------3\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------3")
+ }
+
+ list = append(list, 0)
+ result = IsDistinct_int64(list)
+ fmt.Printf("list:%v,result:%v-------4\n", list, result)
+ if result {
+ t.Errorf("it's should be false, but now true-------4")
+ }
+}
diff --git a/.svn/pristine/3b/3bad0f0187ec9411b0df5744d9cd02879fa239f4.svn-base b/.svn/pristine/3b/3bad0f0187ec9411b0df5744d9cd02879fa239f4.svn-base
new file mode 100644
index 0000000..df565f6
--- /dev/null
+++ b/.svn/pristine/3b/3bad0f0187ec9411b0df5744d9cd02879fa239f4.svn-base
@@ -0,0 +1,88 @@
+package logSqlSync
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+
+ "goutil/logUtil"
+)
+
+// 错误信息记录表是否已经初始化
+var ifSyncErrorInfoTableInited bool = false
+
+// 同步的错误信息处理对象
+type syncErrorInfo struct {
+ // 数据库连接对象
+ db *sql.DB
+}
+
+// 初始化表信息
+func (this *syncErrorInfo) init() error {
+ // 初始化表结构
+ if ifSyncErrorInfoTableInited == false {
+ err := this.initTable(this.db)
+ if err == nil {
+ ifSyncErrorInfoTableInited = true
+ }
+
+ return err
+ }
+
+ return nil
+}
+
+// 把同步信息更新到数据库
+// data:待更新的数据
+// 返回值:
+// error:错误信息
+func (this *syncErrorInfo) AddErrorSql(tran *sql.Tx, data string, errMsg string) error {
+ updateSql := "INSERT INTO `sync_error_info` (`SqlString`,`ExecuteTime`,`RetryCount`,`ErrMessage`) VALUES(?,?,?,?);"
+
+ var err error
+ if tran != nil {
+ _, err = tran.Exec(updateSql, data, time.Now(), 0, errMsg)
+ } else {
+ _, err = this.db.Exec(updateSql, data, time.Now(), 0, errMsg)
+ }
+
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncErrorInfo.AddErrorSql Error:%s", err.Error()))
+ }
+
+ return err
+}
+
+// 初始化同步信息表结构
+// db:数据库连接对象
+func (this *syncErrorInfo) initTable(db *sql.DB) error {
+ // 创建同步信息表
+ createTableSql := `CREATE TABLE IF NOT EXISTS sync_error_info (
+ Id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增Id',
+ SqlString varchar(1024) NOT NULL COMMENT '执行的sql',
+ ExecuteTime datetime NOT NULL COMMENT '最近一次执行时间',
+ RetryCount int NOT NULL COMMENT '重试次数',
+ ErrMessage text NULL COMMENT '执行错误的信息',
+ PRIMARY KEY (Id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='未执行成功的sql数据';`
+ if _, err := db.Exec(createTableSql); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncErrorInfo.initTable Error:%s", err.Error()))
+ return err
+ }
+
+ return nil
+}
+
+// 创建同步信息对象
+// _db:数据库连接对象
+// 返回值:
+// 同步信息对象
+func newSyncErrorInfoObject(_db *sql.DB) (result *syncErrorInfo, err error) {
+ result = &syncErrorInfo{
+ db: _db,
+ }
+
+ err = result.init()
+
+ return result, err
+}
diff --git a/.svn/pristine/3c/3c161a0814b5fbe104eac0a7b7d76bf8dd007800.svn-base b/.svn/pristine/3c/3c161a0814b5fbe104eac0a7b7d76bf8dd007800.svn-base
new file mode 100644
index 0000000..de20829
--- /dev/null
+++ b/.svn/pristine/3c/3c161a0814b5fbe104eac0a7b7d76bf8dd007800.svn-base
@@ -0,0 +1,56 @@
+package remark
+
+import (
+ "common/httpServer"
+ "fmt"
+ "net/http"
+
+ "common/webServer"
+)
+
+// init
+// @description: init
+// parameter:
+// return:
+func init() {
+ webServer.RegisterRemarkFunc(remarkdCallback)
+ httpServer.RegisterRemarkFunc(remarkdCallback)
+}
+
+// remarkdCallback
+// @description: remarkdCallback
+// parameter:
+// @w: w
+// @r: r
+// return:
+func remarkdCallback(w http.ResponseWriter, r *http.Request) {
+
+ for index, moduleItem := range remarksSlice {
+ // 输出模块信息
+ fmt.Fprintf(w, fmt.Sprintf("%d、%s【Name:%s Author:%s Mendor:%s Date:%s】\n", index+1, moduleItem.Desc, moduleItem.Name, moduleItem.Author, moduleItem.Mendor, moduleItem.Date))
+
+ // 输出方法列表信息
+ for subIndex, methodItem := range moduleItem.MethodRemarkSlice {
+ fmt.Fprintf(w, fmt.Sprintf(" %d.%d、%s【Name:%s Author:%s Mendor:%s Date:%s】\n", index+1, subIndex+1, methodItem.Desc, methodItem.Name, methodItem.Author, methodItem.Mendor, methodItem.Date))
+
+ fmt.Fprintln(w, " \t输入参数:")
+ if len(methodItem.InParam) > 0 {
+ for _, param := range methodItem.InParam {
+ fmt.Fprintln(w, " ", param)
+ }
+ } else {
+ fmt.Fprintln(w, " ", "无")
+ }
+
+ fmt.Fprintln(w, " \t输出参数:")
+ if methodItem.OutParam != "" {
+ fmt.Fprintln(w, " ", methodItem.OutParam)
+ } else {
+ fmt.Fprintln(w, " ", "无")
+ }
+
+ fmt.Fprintln(w)
+ }
+ }
+ return
+}
diff --git a/.svn/pristine/3c/3ca8972a3836e96a64416fbbd2ebafdebd1fc2ab.svn-base b/.svn/pristine/3c/3ca8972a3836e96a64416fbbd2ebafdebd1fc2ab.svn-base
new file mode 100644
index 0000000..3a149be
--- /dev/null
+++ b/.svn/pristine/3c/3ca8972a3836e96a64416fbbd2ebafdebd1fc2ab.svn-base
@@ -0,0 +1,46 @@
+// ************************************
+// @package: handleMgr
+// @description: 反射类-请求对象
+// @author:
+// @revision history:
+// @create date: 2022-02-23 16:33:53
+// ************************************
+
+package handleMgr
+
+// RequestObject 请求对象
+type RequestObject struct {
+ // 请求的模块名称
+ ModuleName string
+
+ // 请求的方法名称
+ MethodName string
+
+ // 请求的参数数组
+ Parameters []interface{}
+
+ // 是否处理返回值
+ IsHaveResult bool
+
+ // 执行完成,返回chan监控
+ ResultChan chan *ResponseObject
+}
+
+// NewRequestObject
+// @description:
+// parameter:
+// @moduleName:模块名名称
+// @methodName:执行方法名称
+// @parameters:方法参数
+// @isHaveResult:是否处理返回值
+// return:
+// @*RequestObject:
+func NewRequestObject(moduleName string, methodName string, parameters []interface{}, isHaveResult bool) *RequestObject {
+ return &RequestObject{
+ ModuleName: moduleName,
+ MethodName: methodName,
+ Parameters: parameters,
+ IsHaveResult: isHaveResult,
+ ResultChan: make(chan *ResponseObject, 1),
+ }
+}
diff --git a/.svn/pristine/3e/3e543ef3da7294f5fed68348b9d711e4e403aeb2.svn-base b/.svn/pristine/3e/3e543ef3da7294f5fed68348b9d711e4e403aeb2.svn-base
new file mode 100644
index 0000000000000000000000000000000000000000..910b8dd4f95a323fb4694642b98cc2f1468600ec
GIT binary patch
literal 5985
zcmZ{o1yod98-|DOt`P;16eOfOhmh{Bp+OpE=$7v8xTHuof;7@4DTqUhG)RZQkKV$2
z?|;@hbIzHy&wkc-_Pf9R?N><_0TCVW3@axjiD?#!|VG
zY*+1mML^YSkd>+K-$DGmyo3#`T&eVFwj{Q&xv5F)rSR}RmI@56i@IymG4M5>Pwa?s
zftAu^b-|ju%8m4s?$v>rCv(hkIA+;E8heuABcgeo3+a+5Ag-jt6K79W6GxcV)qBy{
zD8X!uzz~(2rUllBL`A7u5n$pWl@=4RWUZ14WY6|v%@9hvMnLmu-=c
ztlF8Psf}b};n7w0m66k+d?yE4bD1fLY&>KVtEx~lEY$8#h{@hn+T2CEjS923EcVgdl
zI0VN=bh8HLv>dUGBZH$y%J2$2w=km1X0A+B^qr+#z%myWxMYE7737y1{Pf2x(|}gS
z@>M~*<;j$>BJ0+CR_pjKZ4xT|3ue9H?x6zjhiYfHAkAWCWDS-&!J~7&`HY7<-ms5N
zED*}9n^QhQ|J~Z>-;w^F$^vTX+U)g=@%wjEIRg&>Ah}*Pisvaydr=kgmrWbY%xQok!*E`PqP`Sqk)UElr$yg*wSwduwaa|l
zm9}YX-jJdX*VXN`KJ41IpE)^M3xTYrF9dfuWbxKA4Hdy0<4_2-OX~F(*~=v%Y*E59
zZ24bQhTMnt*)%-cJYo0(cs6OU_v>j~Wdl%cI}Q`JaQed+Q=G|kz(}9KTc^!iJ7s4s_LywkK>I-qQoU1lLR1h*ozQ0Hk&_(h4i=!
zIjJmWQd^2e@-DLa8Gopagz8h2OHfUulF>_L{1pXBRT!3uQIv#@S88N-<{ODChB+
z@KbmYj=#R3%YV@%uNSS=jGHh1PQ+st5mnVsQLM>lMVaQ-@9+YbXiJKO`K8d9TrTBw
z>zA0$nMSG^CS-c$Q746ZO-qZ{wnf=lX-F$5C6A{hYlfcdm5E-5`tpNS
zuv>T~@VT{Ha1b#n0}O?`>$4Vy-c4!tBixKg_e37}S*0bhSJ8yYW6G9OxJonEJ(X%f
zH!Ct;1){K<)+O^{R?|cdO<+1cI|CyTU#PVYZ);!I)EVP(v6$|9_V$Rk8|l_`z$
zW*|8+YuHerg%RMyYxnc&wrpfpZf|LKxPk<&
zs7s@f4=Yh^k@1}3kWV!Yj~g5F9~LZPMyJQ;1ytJ@YO>5bPHg#geeh1xhE3CEp3Gao
z8dNZR7N78ux9slk(iGQw)Loo#F9g|>vp;i}10C*QPacZ!i;}~eRkd!_1g<6=CBEj{
zo#opy7-uRB*86BpE&6ctT^$$pIRMz3NhQ<4`e>l;1p%#oXnDcQM1ophbtlqrd?XtM
zu$aJQRbb8ZhQm2-OCa`z0O`Z{rEXKu0Y2B-k)_S7rsb2IxO4GPwET_AaUNE7mfS>P
zTq$smUPLHs@a{1HZc{IeJV*M0`G0hZwMJ^
zrEBdnX&go+w}8L%1A%I~wys@Ratu5GP>&1%Jh+!1%%OHB5G#ATzp_M<+OGAa$fKLg
zt7p+(u^Nr$5DjxMh1w$t$RO9Z3_X^{oracO54<5D4-|?GVe4UiW7Az}3=Gd0uJJXO
zp1kd{Hfg4b@bpLAi~o8d*q-7!D(Z&4iD*2ZUc?8Og4p!tmd!K24#xM+#+Q8nknnfa
z!*G77`vtY)=}MfPRYC9rXtS`|Mx|X4i|$R%*PFwb(ZhL{ZT=-_NI`K`Z(0Pe9zX=&
z@zwP;*lc%W$=cHs?S)A{wV5uJK5qRnsuQH@0f*pi6bVN=+IOcbZz=&VGLFW8r0&t)
zvHb2V@BjvvPZ%eosBhu8_9Fa*V1cS$L)Im===$3sx;N4k^=^dh$EN`>k}Q_(T^!Hd
zvC5)UxPp)`XtsM{TC`KD{XE@3^8K+@wYr4Ja2MhQL)dAnWYpG-zDkT0!8q4C6Z`=o
zYwGqlMc0KhpOAO_BIydpJ}rD0l|{5^`%x)6iH4T%=Z#9CI?V7O6jtR&baGL1JTvM>
z$k}*%Y^6A~k#llESuq*8UnNYCVDM};L(8iH(J?QVtF6RukE%%IGTG1^NB1J?e&a*`
zBGvB@hFQQ+5{D8xb}Ym;zb?bpmO0(5>_!u&qlNh3t=O$xWS38R(7Y*W6LQW*6bs3=
zVL}p+38#Z+8t$oZM$(aXHG2#+SfOWyPNK#Vty87wQ#B2f0KyXlYdgiC8>gqAD>2yv$%UkBib2`%S_Fp_Rvo1kc;vGv5ZbxOGIq?jKTk#IhqhKLqsY)Z
z`5pS%wUjR0m8o7W+tZ7`5LgW9&N
zqM4u*PklAz4S_pzqcitez5*CTp=}(&SL1q!1Q}0Y#ofYt
z>o2Qu#jKxIN-8f)6M)HR%KE*#(#1QiLBBIE_1lLxKnHQPPFAAmOMH&K&<~>J3LEPN
zML{`VrXw%gbJHQWwE{53clM*f!nNHW54SxpYEry6h7ttTo_(s?pL{#e>PhWmN;(px
z8w{=X@Qm{)!^&**HzF^VlYqXed$ZSl$#R<^TkBRzGX0&A^%IX2==m^V-*Tq~x|LJ?
zpd(^QHF1#`__cq1WL-~P#g~I5WbCv`F4c$^{dxo6t#?fnX!4>Z-);TH^
zl(j6etZ3w_+Fx$ebPLz1A%ep6c+S1fz=_lrucbC4#D{E}MKiCWBvLTHC}=(oAkO-%
zm2%zbR)8TJGaX7RRcNN-u*xV4qDNuA-lyk^2ZXPYZV
z-X(aJ?Kvt)z`Lj4m%njXH6#Ea7T0^h;SVH_p*bqY*Pd*b)IWAt);?LyhGPN@brJ39
zpS@3t@2feMVs^D0BVvq?4B@(z0G*oBk>N}oxE+?`9Eys6MXsik*pc}R$fKV$jL}Bv
zuUT@0lqZ-l9)r;fr7CN`h7frrGzSbeC71bTwvnwNmIkD%vY5*liUoTpGnds+nQev*
zTGB8>=zOmR@}EFfKL{4~K&&^Re!IH5#z(HxDRh58ba+vOXkvjZQiohHaZ~Kp8P`*px8?Y#a%ve
zyvrwK_Y`4kWM^by1~RjQnEk4YAK67{zmjL2fyhc^A0EN13-}bfddZepvDVTFUqO+U
z4H=!mOqY9Bs;{@`R16kWk%3xTF)ciqz@>SGkxhM_E}x6rwS4Wi@YQ>vk9(LTSfXlk
zJkJ(xwql<(T3sak3({woIu6xXMKd6zg}P=5kp{^LkRJS)R1JOve-JH0ew;(zXJe0D
zg)ME@c|M=dWn@FYaFUPc#1M8wdY~yZVA(@63ZJk_B!d5m)3M``NIvw8cpYOnY}@9g
zs0uN;`gQo)D;r^DxGDx^J=LGRkeJr558iV;c@Q@gq;5q$(`DaQjfR49+;@Z!{tT&w;h%d1>^917$DU8%Uh`Ts-Q|A1yvItf$M7
zw-qW3%=2PwtB8o&qQ=$nh_tFB2u=VKte@?_gR-nQv4kuCkd~j*x37kG(n>%A
z0D$+UWq-F;+5fGoth+UfK$OsX;eu#Ys9#d-)Vq-4>5Gn-075UA9ryN@4=cYe9=)1U
z*z|5l0euubDeeS{6=kTg{6@~e4z1z^#;BFhVb*qk5V
zq#^@~cAHQ^XsCJ1$g_2(+1k09j-+*;rA_D1z3>PDv1XRtGMwcx}~
ze7-z|z{GfS^x)7=^(GK}nB0wXY2mn=s&OE+c96Og?D#H&SWwBx567Cs|K&s7NdoH$j=twa(BS!c{(2;&u0N(eF?deNB$wDipx=Y)Oh{lIg9OT
z`Naz~z6uv|dQ=k^g5MWbVsc+o@(GiPNtb#v2fglyba1z&?LIeef;q&q5|Ea-N3p?{pTPP7I&vi8@l#E74Mdhx=Qa4vufHBX*`LPup+K_=j;QuT5INN~^F MAX_POLLING_WAIT_SECONDS {
+ pollingWaitSeconds = MAX_POLLING_WAIT_SECONDS
+ }
+
+ return pollingWaitSeconds
+}
+
+// 验证批量处理的列表
+func (this *Queue) validBatchList(list []string) error {
+ if list == nil || len(list) == 0 {
+ return errors.New(EMPTY_BATCH_LIST_ERROR)
+ }
+ if len(list) > MAX_BATCH_COUNT {
+ return errors.New(EXCEED_MAX_BATCH_COUNT_ERROR)
+ }
+
+ return nil
+}
+
+// error:错误对象
+func (this *Queue) GetQueueAttributes() (err error) {
+ // 逻辑处理
+ requestObj := NewGetQueueAttributesRequest()
+ responseObj := NewGetQueueAttributesResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ return
+}
+
+// SendMessage 发送单条消息
+// 参数
+// message:消息内容
+// delaySeconds:单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
+// 返回值
+// error:错误对象
+func (this *Queue) SendMessage(message string, delaySeconds int) (err error) {
+ // 参数验证和处理
+ if message == "" {
+ err = errors.New(EMPTY_MESSAGE_ERROR)
+ return
+ }
+ delaySeconds = this.handleDelaySeconds(delaySeconds)
+
+ // 逻辑处理
+ requestObj := NewSendMessageRequest(message, delaySeconds)
+ responseObj := NewSendMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ return
+}
+
+// BatchSendMessage 批量发送消息
+// 参数
+// messageList:消息内容列表
+// delaySeconds:单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
+// 返回值
+// error:错误对象
+func (this *Queue) BatchSendMessage(messageList []string, delaySeconds int) (err error) {
+ // 参数验证和处理
+ err = this.validBatchList(messageList)
+ if err != nil {
+ return
+ }
+ delaySeconds = this.handleDelaySeconds(delaySeconds)
+
+ // 逻辑处理
+ requestObj := NewBatchSendMessageRequest(messageList, delaySeconds)
+ responseObj := NewBatchSendMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ return
+}
+
+// Receive 消费单条消息
+// pollingWaitSeconds:本次请求的长轮询等待时间。取值范围0 - 30秒,如果不设置该参数,则默认使用队列属性中的 pollingWaitSeconds 值。
+// 返回值
+// receiptHandle:消息句柄
+// message:消息内容
+// exist:是否存在数据
+// err:错误对象
+func (this *Queue) ReceiveMessage(pollingWaitSeconds int) (receiptHandle, message string, exist bool, err error) {
+ // 参数验证和处理
+ pollingWaitSeconds = this.handlePollingWaitSeconds(pollingWaitSeconds)
+
+ // 逻辑处理
+ requestObj := NewReceiveMessageRequest(pollingWaitSeconds)
+ responseObj := NewReceiveMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ // 忽略掉没有消息的错误
+ if responseObj.HaveNoMessage() {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ receiptHandle = responseObj.ReceiptHandle
+ message = responseObj.MsgBody
+ exist = true
+
+ return
+}
+
+// BatchReceiveMessage 批量消费消息
+// 参数
+// numOfMsg:本次消费的消息数量
+// pollingWaitSeconds:本次请求的长轮询等待时间。取值范围0 - 30秒,如果不设置该参数,则默认使用队列属性中的 pollingWaitSeconds 值。
+// 返回值
+// receiptHandleList:消息句柄列表
+// messageList:消息内容列表
+// exist:是否存在数据
+// err:错误对象
+func (this *Queue) BatchReceiveMessage(numOfMsg, pollingWaitSeconds int) (receiptHandleList, messageList []string, exist bool, err error) {
+ // 参数验证和处理
+ if numOfMsg > MAX_BATCH_COUNT {
+ err = errors.New(EXCEED_MAX_BATCH_COUNT_ERROR)
+ return
+ }
+ pollingWaitSeconds = this.handlePollingWaitSeconds(pollingWaitSeconds)
+
+ // 逻辑处理
+ requestObj := NewBatchReceiveMessageRequest(numOfMsg, pollingWaitSeconds)
+ responseObj := NewBatchReceiveMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ // 忽略掉没有消息的错误
+ if responseObj.HaveNoMessage() {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ // 组装返回
+ receiptHandleList = make([]string, 0, numOfMsg)
+ messageList = make([]string, 0, numOfMsg)
+ for _, msgInfo := range responseObj.MsgInfoList {
+ receiptHandleList = append(receiptHandleList, msgInfo.ReceiptHandle)
+ messageList = append(messageList, msgInfo.MsgBody)
+ }
+ exist = true
+
+ return
+}
+
+// DeleteMessage 删除单条消息
+// 参数
+// receiptHandle:消息句柄
+// 返回值
+// error:错误对象
+func (this *Queue) DeleteMessage(receiptHandle string) (err error) {
+ // 参数验证和处理
+ if receiptHandle == "" {
+ err = errors.New(EMPTY_HANDLE_ERROR)
+ return
+ }
+
+ // 逻辑处理
+ requestObj := NewDeleteMessageRequest(receiptHandle)
+ responseObj := NewDeleteMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return err
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ return
+ }
+
+ return
+}
+
+// BatchDeleteMessage 批量删除消息
+// 参数
+// receiptHandleList:消息句柄列表
+// 返回值
+// errorMap:删除错误的字典(key:删除失败的消息句柄;value:删除失败的原因)
+// err:错误对象
+func (this *Queue) BatchDeleteMessage(receiptHandleList []string) (errorMap map[string]string, err error) {
+ // 参数验证和处理
+ err = this.validBatchList(receiptHandleList)
+ if err != nil {
+ return
+ }
+
+ // 逻辑处理
+ requestObj := NewBatchDeleteMessageRequest(receiptHandleList)
+ responseObj := NewBatchDeleteMessageResponse()
+
+ // 发送请求
+ err = this.action(requestObj, &responseObj)
+ if err != nil {
+ return
+ }
+
+ if responseObj.IsFailure() {
+ err = errors.New(responseObj.Message)
+ // 组装返回
+ errorMap = make(map[string]string)
+ for _, errInfo := range responseObj.ErrorList {
+ errorMap[errInfo.ReceiptHandle] = errInfo.Message
+ }
+ return
+ }
+
+ return
+}
+
+// 创建新的Queue对象
+func NewQueue(region, queueName, secretId, secretKey string) *Queue {
+ queueConfigObj := &QueueConfig{
+ Region: region,
+ QueueName: queueName,
+ SecretId: secretId,
+ SecretKey: secretKey,
+ }
+
+ return NewQueueByConfig(queueConfigObj)
+}
+
+// 通过队列配置对象创建新的Queue对象
+func NewQueueByConfig(queueConfigObj *QueueConfig) *Queue {
+ queueObj := &Queue{
+ region: queueConfigObj.Region,
+ network: MQ_NETWORK_INTERNAL,
+ queueName: queueConfigObj.QueueName,
+ secretId: queueConfigObj.SecretId,
+ secretKey: queueConfigObj.SecretKey,
+ }
+
+ err := queueObj.GetQueueAttributes()
+ if err != nil {
+ if strings.Contains(err.Error(), MQ_NETWORK_INTERNAL) {
+ queueObj.network = MQ_NETWORK_PUBLIC
+ }
+ }
+
+ return queueObj
+}
diff --git a/.svn/pristine/41/414778273450f16557c41cc40bc68d5bca11839e.svn-base b/.svn/pristine/41/414778273450f16557c41cc40bc68d5bca11839e.svn-base
new file mode 100644
index 0000000..5eb1109
--- /dev/null
+++ b/.svn/pristine/41/414778273450f16557c41cc40bc68d5bca11839e.svn-base
@@ -0,0 +1,109 @@
+package configUtil
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+)
+
+// 读取JSON格式的配置文件
+// config_file_path:配置文件路径
+// 返回值:
+// 配置内容的map格式数组
+// 错误对象
+func ReadJsonConfig_Array(config_file_path string) ([]map[string]interface{}, error) {
+ // 读取配置文件(一次性读取整个文件,则使用ioutil)
+ bytes, err := ioutil.ReadFile(config_file_path)
+ if err != nil {
+ return nil, fmt.Errorf("读取配置文件的内容出错:%s", err)
+ }
+
+ // 使用json反序列化
+ config := make([]map[string]interface{}, 0, 4)
+ if err = json.Unmarshal(bytes, &config); err != nil {
+ return nil, fmt.Errorf("反序列化配置文件的内容出错:%s", err)
+ }
+
+ return config, nil
+}
+
+func getConfigValue(config []map[string]interface{}, configName string) (configValue interface{}, err error) {
+ var exist bool
+ for _, configItem := range config {
+ if configValue, exist = configItem[configName]; exist {
+ break
+ }
+ }
+
+ if !exist {
+ err = fmt.Errorf("不存在名为%s的配置或配置为空", configName)
+ }
+
+ return
+}
+
+// 从config配置中获取int类型的配置值
+// config:从config文件中反序列化出来的map对象
+// configName:配置名称
+// 返回值:
+// 配置值
+// 错误对象
+func ReadIntJsonValue_Array(config []map[string]interface{}, configName string) (value int, err error) {
+ configValue, err := getConfigValue(config, configName)
+ if err != nil {
+ return
+ }
+
+ configValue_float, ok := configValue.(float64)
+ if !ok {
+ err = fmt.Errorf("%s必须为int型", configName)
+ return
+ }
+ value = int(configValue_float)
+
+ return
+}
+
+// 从config配置中获取string类型的配置值
+// config:从config文件中反序列化出来的map对象
+// configName:配置名称
+// 返回值:
+// 配置值
+// 错误对象
+func ReadStringJsonValue_Array(config []map[string]interface{}, configName string) (value string, err error) {
+ configValue, err := getConfigValue(config, configName)
+ if err != nil {
+ return
+ }
+
+ configValue_string, ok := configValue.(string)
+ if !ok {
+ err = fmt.Errorf("%s必须为string型", configName)
+ return
+ }
+ value = configValue_string
+
+ return
+}
+
+// 从config配置中获取string类型的配置值
+// config:从config文件中反序列化出来的map对象
+// configName:配置名称
+// 返回值:
+// 配置值
+// 错误对象
+func ReadBoolJsonValue_Array(config []map[string]interface{}, configName string) (value bool, err error) {
+ configValue, err := getConfigValue(config, configName)
+ if err != nil {
+ return
+ }
+
+ configValue_bool, ok := configValue.(bool)
+ if !ok {
+ err = fmt.Errorf("%s必须为bool型", configName)
+ return
+ }
+ value = configValue_bool
+
+ return
+}
diff --git a/.svn/pristine/42/428d4b97237af34809acbd8293feabe883b1d689.svn-base b/.svn/pristine/42/428d4b97237af34809acbd8293feabe883b1d689.svn-base
new file mode 100644
index 0000000..68d7660
--- /dev/null
+++ b/.svn/pristine/42/428d4b97237af34809acbd8293feabe883b1d689.svn-base
@@ -0,0 +1,37 @@
+package mathUtil
+
+import (
+ "fmt"
+)
+
+// 获取字节大小的描述信息
+// size:字节大小
+// 返回值:
+// 描述信息
+func GetSizeDesc(size int64) string {
+ str := ""
+
+ // 判断输入是否超过int64的范围
+ if size < 0 || size > (1<<63-1) {
+ return str
+ }
+
+ switch {
+ case size >= 1024*1024*1024*1024*1024*1024:
+ str = fmt.Sprintf("%.2fEB", float64(size)/1024/1024/1024/1024/1024/1024)
+ case size >= 1024*1024*1024*1024*1024:
+ str = fmt.Sprintf("%.2fPB", float64(size)/1024/1024/1024/1024/1024)
+ case size >= 1024*1024*1024*1024:
+ str = fmt.Sprintf("%.2fTB", float64(size)/1024/1024/1024/1024)
+ case size >= 1024*1024*1024:
+ str = fmt.Sprintf("%.2fGB", float64(size)/1024/1024/1024)
+ case size >= 1024*1024:
+ str = fmt.Sprintf("%dMB", size/1024/1024)
+ case size >= 1024:
+ str = fmt.Sprintf("%dKB", size/1024)
+ default:
+ str = fmt.Sprintf("%dB", size)
+ }
+
+ return str
+}
diff --git a/.svn/pristine/43/431951efd695edc9cc00309e90205cafdb4ea415.svn-base b/.svn/pristine/43/431951efd695edc9cc00309e90205cafdb4ea415.svn-base
new file mode 100644
index 0000000..ecfe708
--- /dev/null
+++ b/.svn/pristine/43/431951efd695edc9cc00309e90205cafdb4ea415.svn-base
@@ -0,0 +1,233 @@
+/*
+未实现的哈希表方法:
+MOVE、SCAN、SORT、FLUSHDB、FLUSHALL、SELECT、SWAPDB
+*/
+package redisUtil
+
+import (
+ "github.com/gomodule/redigo/redis"
+)
+
+/*
+EXPIRE key seconds
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
+
+在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。
+
+生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆写(overwrite),这意味着,如果一个命令只是修改(alter)一个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。
+
+比如说,对一个 key 执行 INCR 命令,对一个列表进行 LPUSH 命令,或者对一个哈希表执行 HSET 命令,这类操作都不会修改 key 本身的生存时间。
+
+另一方面,如果使用 RENAME 对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。
+
+RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。
+
+使用 PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。
+
+更新生存时间
+可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。
+
+过期时间的精确度
+在 Redis 2.4 版本中,过期时间的延迟在 1 秒钟之内 —— 也即是,就算 key 已经过期,但它还是可能在过期之后一秒钟之内被访问到,而在新的 Redis 2.6 版本中,延迟被降低到 1 毫秒之内。
+
+Redis 2.1.3 之前的不同之处
+在 Redis 2.1.3 之前的版本中,修改一个带有生存时间的 key 会导致整个 key 被删除,这一行为是受当时复制(replication)层的限制而作出的,现在这一限制已经被修复。
+
+返回值
+设置成功返回 1 。 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。
+*/
+func (this *RedisPool) Expire(key string, seconds int64) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ if result, err = redis.Int(conn.Do("EXPIRE", key, seconds)); err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+EXPIREAT key timestamp
+可用版本: >= 1.2.0
+时间复杂度: O(1)
+EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。
+
+不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
+
+返回值
+如果生存时间设置成功,返回 1 ; 当 key 不存在或没办法设置生存时间,返回 0 。
+*/
+func (this *RedisPool) ExpireAt(key string, timestamp int64) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ if result, err = redis.Int(conn.Do("EXPIREAT", key, timestamp)); err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+TTL key
+可用版本: >= 1.0.0
+时间复杂度: O(1)
+以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
+
+返回值
+当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。
+
+Note
+
+在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
+*/
+func (this *RedisPool) TTL(key string) (ttl int64, exist, persisted bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ ttl, err = redis.Int64(conn.Do("TTL", key))
+ if err != nil {
+ return
+ }
+
+ if ttl == -2 {
+ exist = false
+ persisted = false
+ } else if ttl == -1 {
+ exist = true
+ persisted = true
+ } else {
+ exist = true
+ persisted = false
+ }
+
+ return
+}
+
+/*
+PERSIST key
+可用版本: >= 2.2.0
+时间复杂度: O(1)
+移除给定 key 的生存时间,将这个 key 从“易失的”(带生存时间 key )转换成“持久的”(一个不带生存时间、永不过期的 key )。
+
+返回值
+当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 。
+*/
+func (this *RedisPool) Persist(key string) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ if result, err = redis.Int(conn.Do("PERSIST", key)); err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+PEXPIRE key milliseconds
+可用版本: >= 2.6.0
+时间复杂度: O(1)
+这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
+
+返回值
+设置成功,返回 1 key 不存在或设置失败,返回 0
+*/
+func (this *RedisPool) PExpire(key string, milliseconds int64) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ if result, err = redis.Int(conn.Do("PEXPIRE", key, milliseconds)); err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+PEXPIREAT key milliseconds-timestamp
+可用版本: >= 2.6.0
+时间复杂度: O(1)
+这个命令和 expireat 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 expireat 那样,以秒为单位。
+
+返回值
+如果生存时间设置成功,返回 1 。 当 key 不存在或没办法设置生存时间时,返回 0 。(查看 EXPIRE key seconds 命令获取更多信息)
+*/
+func (this *RedisPool) PExpireAt(key string, milliseconds_timestamp int64) (successful bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ var result int
+ if result, err = redis.Int(conn.Do("PEXPIREAT", key, milliseconds_timestamp)); err != nil {
+ return
+ }
+
+ if result == 1 {
+ successful = true
+ }
+
+ return
+}
+
+/*
+PTTL key
+可用版本: >= 2.6.0
+复杂度: O(1)
+这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
+
+返回值
+当 key 不存在时,返回 -2 。
+
+当 key 存在但没有设置剩余生存时间时,返回 -1 。
+
+否则,以毫秒为单位,返回 key 的剩余生存时间。
+
+Note
+
+在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
+*/
+func (this *RedisPool) PTTL(key string) (pttl int64, exist bool, persisted bool, err error) {
+ conn := this.GetConnection()
+ defer conn.Close()
+
+ pttl, err = redis.Int64(conn.Do("PTTL", key))
+ if err != nil {
+ return
+ }
+
+ if pttl == -2 {
+ exist = false
+ persisted = false
+ } else if pttl == -1 {
+ exist = true
+ persisted = true
+ } else {
+ exist = true
+ persisted = false
+ }
+
+ return
+}
diff --git a/.svn/pristine/43/432489717638beef3ca372b2de090fd58b2e17d7.svn-base b/.svn/pristine/43/432489717638beef3ca372b2de090fd58b2e17d7.svn-base
new file mode 100644
index 0000000..73b2ef9
--- /dev/null
+++ b/.svn/pristine/43/432489717638beef3ca372b2de090fd58b2e17d7.svn-base
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# 查找 adminServer 的 PID
+PID=$(pgrep adminServer)
+
+if [ -z "$PID" ]; then
+ echo "adminServer 进程未找到"
+else
+ echo "停止中... (PID: $PID)"
+ kill $PID
+ if [ $? -eq 0 ]; then
+ echo "adminServer 进程已终止 (PID: $PID)"
+ else
+ echo "无法终止 adminServer 进程 (PID: $PID)"
+ fi
+fi
diff --git a/.svn/pristine/43/4338e30fb77af67f2f9564918a01fa309f8f6815.svn-base b/.svn/pristine/43/4338e30fb77af67f2f9564918a01fa309f8f6815.svn-base
new file mode 100644
index 0000000..2ace17a
--- /dev/null
+++ b/.svn/pristine/43/4338e30fb77af67f2f9564918a01fa309f8f6815.svn-base
@@ -0,0 +1,52 @@
+package logUtil
+
+// ILog
+// @description: 日志接口
+type ILog interface {
+ // InfoLog
+ // @description: 信息日志记录
+ // parameter:
+ // @format:日志格式
+ // @args:参数列表
+ // return:
+ InfoLog(format string, args ...interface{})
+
+ // DebugLog
+ // @description: 调试日志记录
+ // parameter:
+ // @format:日志格式
+ // @args:参数列表
+ // return:
+ DebugLog(format string, args ...interface{})
+
+ // WarnLog
+ // @description: 警告日志记录
+ // parameter:
+ // @format:日志格式
+ // @args:参数列表
+ // return:
+ WarnLog(format string, args ...interface{})
+
+ // ErrorLog
+ // @description: 错误日志记录
+ // parameter:
+ // @format:日志格式
+ // @args:参数列表
+ // return:
+ ErrorLog(format string, args ...interface{})
+
+ // FatalLog
+ // @description: 致命错误日志记录
+ // parameter:
+ // @format:日志格式
+ // @args:参数列表
+ // return:
+ FatalLog(format string, args ...interface{})
+
+ // CloseLog
+ // @description: 关闭日志
+ // parameter:
+ // @waitFinish:是否等待日志
+ // return:
+ CloseLog(waitFinish bool)
+}
diff --git a/.svn/pristine/43/43442b142f5c5969f7878c2074d3b3ebe0f9c003.svn-base b/.svn/pristine/43/43442b142f5c5969f7878c2074d3b3ebe0f9c003.svn-base
new file mode 100644
index 0000000..1fff6e6
--- /dev/null
+++ b/.svn/pristine/43/43442b142f5c5969f7878c2074d3b3ebe0f9c003.svn-base
@@ -0,0 +1,450 @@
+// ************************************
+// @package: websocketServer
+// @description: websocket管理
+// @author:
+// @revision history:
+// @create date: 2022-02-18 15:38:17
+// ************************************
+package websocketServer
+
+import (
+ "errors"
+ "github.com/gorilla/websocket"
+ routineCtrlUtil "goutil/routineCtrlUtil"
+ "sync"
+ "time"
+)
+
+const (
+ // 默认广播并发数
+ con_DEFAULT_BROADCAST_CONCURRENT = 10
+)
+
+// connManager
+// @description: websocket连接管理
+type connManager struct {
+ // 是否禁止新连接
+ disableNewConn bool
+
+ // 广播并发数
+ broadcastConcurrent int
+
+ // websocket服务端配置结构
+ upgrader *websocket.Upgrader
+
+ // 广播锁-限制 消息广播/关闭所有连接 并发访问
+ muBroadcast sync.Mutex
+
+ // 连接池map写锁(增加/删除)
+ muAllConns sync.Mutex
+
+ // 连接池-所有已连接的websocket
+ allConns map[*websocket.Conn]*Context
+
+ //-------------------
+ // 心跳控制
+
+ // 接收到Ping消息时,是否自动回复Pong
+ autuPong bool
+
+ // 心跳周期
+ heartbeatCycle time.Duration
+
+ // 断连周期数(超过几个心跳周期即自动关闭连接);设置为0即关闭心跳检测功能
+ heartbeatCloseCount int
+
+ // 是否已开启心跳检测协程
+ isHeartbeatDetectStart bool
+}
+
+// heartbeatDetect
+// @description: 开启心跳检测协程
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+func (connMgr *connManager) heartbeatDetect() {
+ // 限制每个websocket连接管理只开启一个心跳检测协程
+ if !connMgr.isHeartbeatDetectStart {
+ connMgr.isHeartbeatDetectStart = true
+
+ // 开启心跳检测协程
+ go func() {
+ for {
+ if connMgr.heartbeatCloseCount <= 0 {
+ // 心跳检测功能已关闭;每秒检测此标志
+ time.Sleep(time.Second)
+ continue
+ }
+
+ // 心跳检测功能已开启
+
+ connMgr.muAllConns.Lock() // 连接池map锁
+ ctxs_timeout := make([]*Context, 0, len(connMgr.allConns)) // 存放心跳超时,需要关闭的websocket环境
+ for _, ctx := range connMgr.allConns {
+ if time.Since(ctx.heartbeat) > (connMgr.heartbeatCycle*time.Duration(connMgr.heartbeatCloseCount) + 1) {
+ // 心跳超时,需要关闭的websocket环境加入列表
+ ctxs_timeout = append(ctxs_timeout, ctx)
+ }
+ }
+ connMgr.muAllConns.Unlock() // 连接池map及时解锁
+
+ // 关闭所有心跳超时的连接
+ func() {
+ // 获取广播并发数
+ broadcastConcurrent := connMgr.broadcastConcurrent
+ if broadcastConcurrent <= 0 {
+ broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
+ }
+
+ // 协程并发限制
+ rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
+ for _, ctx := range ctxs_timeout {
+ ctxTemp := ctx
+ rtCtrl.Run(func(arg interface{}) {
+ // 执行受限并发函数
+ ctxTemp.Close()
+ }, nil)
+ }
+
+ // 等待完成
+ rtCtrl.Wait()
+ }()
+
+ // 休眠半个心跳周期
+ slpTime := time.Duration(connMgr.heartbeatCycle / 2)
+ if slpTime < time.Second {
+ slpTime = time.Second
+ }
+ time.Sleep(slpTime)
+ }
+ }()
+ }
+}
+
+// upgrade
+// @description: 升级为websocket
+// parameter:
+//
+// @receiver connMgr:
+// @ctx: websocket环境
+//
+// return:
+//
+// @*websocket.Conn: 建立的连接对象
+// @error:
+func (connMgr *connManager) upgrade(ctx *Context) (conn *websocket.Conn, err error) {
+ if connMgr.disableNewConn {
+ // 禁止新连接
+ return nil, errors.New("connManager(disableNewConn)")
+ }
+
+ // 建立websocket连接
+ conn, err = connMgr.upgrader.Upgrade(ctx.GetWebServerContext().GetResponseWriter(), ctx.GetWebServerContext().GetRequest(), nil)
+ if err != nil {
+ return
+ }
+
+ // 添加到连接池
+ ctx.conn = conn
+ connMgr.addConn(conn, ctx)
+
+ return
+}
+
+// addConn
+// @description: 添加到连接池
+// parameter:
+//
+// @receiver connMgr:
+// @conn:
+// @ctx:
+//
+// return:
+func (connMgr *connManager) addConn(conn *websocket.Conn, ctx *Context) {
+ connMgr.muAllConns.Lock()
+ defer connMgr.muAllConns.Unlock()
+
+ connMgr.allConns[conn] = ctx
+}
+
+// delConn
+// @description: 将连接从连接池删除
+// parameter:
+//
+// @receiver connMgr:
+// @conn:
+//
+// return:
+func (connMgr *connManager) delConn(conn *websocket.Conn) {
+ connMgr.muAllConns.Lock()
+ defer connMgr.muAllConns.Unlock()
+
+ delete(connMgr.allConns, conn)
+}
+
+// renewAllConnsMap
+// @description: 重新替换一个新allConns的map结构,以免被标记删除的冗余信息造成存储和性能问题
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+//
+// @map[*websocket.Conn]*Context: 返回原内部使用的连接池(现内部已不再使用)
+func (connMgr *connManager) renewAllConnsMap() map[*websocket.Conn]*Context {
+ connMgr.muAllConns.Lock()
+ defer connMgr.muAllConns.Unlock()
+
+ // map拷贝
+ allConnsCopy := make(map[*websocket.Conn]*Context, len(connMgr.allConns))
+ for conn, ctx := range connMgr.allConns {
+ allConnsCopy[conn] = ctx
+ }
+ // map替换;因map删除时只是标记,并非真正删除,使用一段时间后可能会出现大量未使用信息;这里顺便更新一下map
+ connMgr.allConns, allConnsCopy = allConnsCopy, connMgr.allConns
+
+ return allConnsCopy
+}
+
+// SetBroadcastConcurrent
+// @description: 设置广播并发数
+// parameter:
+//
+// @receiver connMgr:
+// @n: 广播并发数
+//
+// return:
+func (connMgr *connManager) SetBroadcastConcurrent(n int) {
+ connMgr.broadcastConcurrent = n
+}
+
+// EnableNewConn
+// @description: 允许新连接
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+func (connMgr *connManager) EnableNewConn() {
+ connMgr.disableNewConn = false
+}
+
+// DisableNewConn
+// @description: 禁用新连接
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+func (connMgr *connManager) DisableNewConn() {
+ connMgr.disableNewConn = true
+}
+
+// MulticastMessage
+// @description: 多播消息(给指定多用户发送消息)
+// parameter:
+//
+// @receiver connMgr:
+// @ctxs: 指定多用户的*Context切片
+// @messageType: websocket类型
+// @data: 发送的数据
+//
+// return:
+//
+// @err: 若有错误,则为最后一个错误
+func (connMgr *connManager) MulticastMessage(ctxs []*Context, messageType int, data []byte) (err error) {
+ // 广播锁,防重入
+ connMgr.muBroadcast.Lock()
+ defer connMgr.muBroadcast.Unlock()
+
+ // 获取广播并发数
+ broadcastConcurrent := connMgr.broadcastConcurrent
+ if broadcastConcurrent <= 0 {
+ broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
+ }
+
+ // 协程并发限制
+ rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
+ var mu sync.Mutex
+ for _, ctx := range ctxs {
+ // 执行受限并发函数
+ // 注意:这里的ctx需要使用参数传入Run;否则随时变化的ctx在闭包内使用时,会出现不符合程序要求逻辑的结果
+ rtCtrl.Run(func(arg interface{}) {
+ ctxTemp, _ := arg.(*Context)
+ e := ctxTemp.SendMessage(messageType, data)
+ if e != nil {
+ mu.Lock()
+ err = e
+ mu.Unlock()
+ }
+ }, ctx)
+ }
+
+ // 等待完成
+ rtCtrl.Wait()
+
+ return
+}
+
+// BroadcastMessage
+// @description: 消息广播
+// parameter:
+//
+// @receiver connMgr:
+// @messageType: websocket类型
+// @data: 发送的数据
+//
+// return:
+//
+// @err: 若有错误,则为最后一个错误
+func (connMgr *connManager) BroadcastMessage(messageType int, data []byte) (err error) {
+ // 广播锁,防重入
+ connMgr.muBroadcast.Lock()
+ defer connMgr.muBroadcast.Unlock()
+
+ // 重新替换一个新allConns的map结构,以免被标记删除的冗余信息造成存储和性能问题
+ allConnsCopy := connMgr.renewAllConnsMap()
+
+ // 获取广播并发数
+ broadcastConcurrent := connMgr.broadcastConcurrent
+ if broadcastConcurrent <= 0 {
+ broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
+ }
+
+ // 协程并发限制
+ rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
+ var mu sync.Mutex
+ for _, ctx := range allConnsCopy {
+ // 执行受限并发函数
+ // 注意:这里的ctx需要使用参数传入Run;否则随时变化的ctx在闭包内使用时,会出现不符合程序要求逻辑的结果
+ rtCtrl.Run(func(arg interface{}) {
+ ctxTemp, _ := arg.(*Context)
+ e := ctxTemp.SendMessage(messageType, data)
+ if e != nil {
+ mu.Lock()
+ err = e
+ mu.Unlock()
+ }
+ }, ctx)
+ }
+
+ // 等待完成
+ rtCtrl.Wait()
+
+ return
+}
+
+// CloseAll
+// @description: 关闭所有连接
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+func (connMgr *connManager) CloseAll() {
+ // 广播锁,防重入
+ connMgr.muBroadcast.Lock()
+ defer connMgr.muBroadcast.Unlock()
+
+ // 重新替换一个新allConns的map结构,以免被标记删除的冗余信息造成存储和性能问题
+ allConnsCopy := connMgr.renewAllConnsMap()
+
+ // 获取广播并发数
+ broadcastConcurrent := connMgr.broadcastConcurrent
+ if broadcastConcurrent <= 0 {
+ broadcastConcurrent = con_DEFAULT_BROADCAST_CONCURRENT
+ }
+
+ // 协程并发限制
+ rtCtrl := routineCtrlUtil.New(broadcastConcurrent)
+ for _, ctx := range allConnsCopy {
+ rtCtrl.Run(func(arg interface{}) {
+ ctxTemp, _ := arg.(*Context)
+ // 执行受限并发函数
+ ctxTemp.Close()
+ }, ctx)
+ }
+
+ // 等待完成
+ rtCtrl.Wait()
+}
+
+// SetUpgrader
+// @description: 设置websocket参数结构
+// parameter:
+//
+// @receiver connMgr:
+// @upgrader: websocket中的websocket.Upgrader结构体指针(可以设置握手超时/读写缓存/是否允许跨域等)
+//
+// return:
+func (connMgr *connManager) SetUpgrader(upgrader *websocket.Upgrader) {
+ connMgr.upgrader = upgrader
+}
+
+// GetUpgrader
+// @description: 获取websocket参数结构
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+//
+// @*websocket.Upgrader: websocket中的websocket.Upgrader结构体指针(可以设置握手超时/读写缓存/是否允许跨域等)
+func (connMgr *connManager) GetUpgrader() *websocket.Upgrader {
+ return connMgr.upgrader
+}
+
+// SetAutoPong
+// @description: 设置接收到Ping消息时,是否自动回复Pong信息
+// parameter:
+//
+// @receiver connMgr:
+// @autuPong:
+//
+// return:
+func (connMgr *connManager) SetAutoPong(autuPong bool) {
+ connMgr.autuPong = autuPong
+}
+
+// GetAutoPong
+// @description: 获取接收到Ping消息时,是否自动回复Pong信息
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+//
+// @bool:
+func (connMgr *connManager) GetAutoPong() bool {
+ return connMgr.autuPong
+}
+
+// SetHeartbeatDetectInfo
+// @description: 设置心跳检测信息
+// parameter:
+//
+// @receiver connMgr:
+// @heartbeatCloseCount: 断连周期数(超过几个心跳周期即自动关闭连接);设置为0即关闭心跳检测功能
+// @heartbeatCycle: 心跳周期
+//
+// return:
+func (connMgr *connManager) SetHeartbeatDetectInfo(heartbeatCloseCount int, heartbeatCycle time.Duration) {
+ connMgr.heartbeatCycle = heartbeatCycle
+ connMgr.heartbeatCloseCount = heartbeatCloseCount
+}
+
+// GetHeartbeatDetectInfo
+// @description: 获取心跳检测信息
+// parameter:
+//
+// @receiver connMgr:
+//
+// return:
+//
+// @heartbeatCloseCount: 断连周期数(超过几个心跳周期即自动关闭连接)
+// @heartbeatCycle: 心跳周期
+func (connMgr *connManager) GetHeartbeatDetectInfo() (heartbeatCloseCount int, heartbeatCycle time.Duration) {
+ return connMgr.heartbeatCloseCount, connMgr.heartbeatCycle
+}
diff --git a/.svn/pristine/43/4385e6c1186639ab7ed02dd5ccd2c781cf61b193.svn-base b/.svn/pristine/43/4385e6c1186639ab7ed02dd5ccd2c781cf61b193.svn-base
new file mode 100644
index 0000000..890a77f
--- /dev/null
+++ b/.svn/pristine/43/4385e6c1186639ab7ed02dd5ccd2c781cf61b193.svn-base
@@ -0,0 +1,46 @@
+package user
+
+import (
+ "common/connection"
+ "goutil/logUtilPlus"
+)
+
+// AddUser 添加用户
+// AddUser 添加新的用户到数据库中。
+// 参数 User: 包含用户信息的对象。
+// 返回值: 插入操作影响的行数和可能发生的错误。
+func AddUser(User *User) (int64, error) {
+
+ //处理一些验证
+
+ // 写入到数据库
+ result := connection.GetUserDB().Create(&User) // 通过数据的指针来创建
+
+ if result.Error != nil {
+ logUtilPlus.ErrorLog("添加用户失败 错误信息:", result.Error.Error())
+ }
+ return User.ID, nil
+}
+
+// GetUserByID 根据用户ID获取用户信息
+func GetUserByID(UserID int64) (*User, error) {
+ var User User
+
+ //缓存判断等一些设置
+
+ result := connection.GetUserDB().First(&User, UserID)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+ return &User, nil
+}
+
+// 用户登录
+func Login(account string, password string) (*User, error) {
+ var User User
+ result := connection.GetUserDB().Where("account = ? AND password = ?", account, password).First(&User)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+ return &User, nil
+}
diff --git a/.svn/pristine/43/4394e6533451632d39ca579614e8ddfbf9781d0f.svn-base b/.svn/pristine/43/4394e6533451632d39ca579614e8ddfbf9781d0f.svn-base
new file mode 100644
index 0000000..33f6b30
--- /dev/null
+++ b/.svn/pristine/43/4394e6533451632d39ca579614e8ddfbf9781d0f.svn-base
@@ -0,0 +1,70 @@
+package intAndBytesUtil
+
+import (
+ "encoding/binary"
+ "testing"
+)
+
+func TestBytesToInt(t *testing.T) {
+ var givenBigEndian []byte = []byte{0, 0, 1, 0}
+ var givenLittleEndian []byte = []byte{0, 1, 0, 0}
+ var expectedInt int32 = 256
+
+ result := BytesToInt32(givenBigEndian, binary.BigEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
+ }
+
+ result = BytesToInt32(givenLittleEndian, binary.LittleEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
+ }
+}
+
+func TestBytesToInt16(t *testing.T) {
+ var givenBigEndian []byte = []byte{1, 0}
+ var givenLittleEndian []byte = []byte{0, 1}
+ var expectedInt int16 = 256
+
+ result := BytesToInt16(givenBigEndian, binary.BigEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
+ }
+
+ result = BytesToInt16(givenLittleEndian, binary.LittleEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
+ }
+}
+
+func TestBytesToInt32(t *testing.T) {
+ var givenBigEndian []byte = []byte{0, 0, 1, 0}
+ var givenLittleEndian []byte = []byte{0, 1, 0, 0}
+ var expectedInt int32 = 256
+
+ result := BytesToInt32(givenBigEndian, binary.BigEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
+ }
+
+ result = BytesToInt32(givenLittleEndian, binary.LittleEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
+ }
+}
+
+func TestBytesToInt64(t *testing.T) {
+ var givenBigEndian []byte = []byte{0, 0, 0, 0, 0, 0, 1, 0}
+ var givenLittleEndian []byte = []byte{0, 1, 0, 0, 0, 0, 0, 0}
+ var expectedInt int64 = 256
+
+ result := BytesToInt64(givenBigEndian, binary.BigEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenBigEndian, result, expectedInt)
+ }
+
+ result = BytesToInt64(givenLittleEndian, binary.LittleEndian)
+ if result != expectedInt {
+ t.Errorf("BytesToInt(%v) failed.Got %v, expected %v", givenLittleEndian, result, expectedInt)
+ }
+}
diff --git a/.svn/pristine/43/43a87b7137557b0aa604619fa267109dfadd8834.svn-base b/.svn/pristine/43/43a87b7137557b0aa604619fa267109dfadd8834.svn-base
new file mode 100644
index 0000000..93600d2
--- /dev/null
+++ b/.svn/pristine/43/43a87b7137557b0aa604619fa267109dfadd8834.svn-base
@@ -0,0 +1,95 @@
+package ensureSendUtil
+
+import (
+ "fmt"
+ "net"
+ "testing"
+ "time"
+
+ "goutil/debugUtil"
+ "goutil/zlibUtil"
+)
+
+// 保存接收的数据用于校验
+var tcp_recv_msg = make([]byte, 0)
+
+func init() {
+ debugUtil.SetDebug(true)
+}
+
+// 创建socket服务器,保存收到的数据
+func server(addr string) net.Listener {
+ listener, err := net.Listen("tcp", addr)
+ if err != nil {
+ panic(err)
+ }
+
+ go func() {
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ return
+ }
+
+ for {
+ buff := make([]byte, 512)
+ _, err := conn.Read(buff)
+ if err != nil {
+ break
+ } else {
+ decompressed, err := zlibUtil.Decompress(buff[4:])
+ if err != nil {
+ panic(err)
+ } else {
+ tcp_recv_msg = append(tcp_recv_msg, decompressed...)
+ }
+ }
+ }
+ }
+ }()
+
+ return listener
+}
+
+func Test_tcp(t *testing.T) {
+ // 开启服务器
+ l := server("127.0.0.1:9559")
+
+ tcp, err := NewTCPSender("./test_tcp", "127.0.0.1:9559")
+ if err != nil {
+ t.Error(err)
+ }
+
+ // 发送消息
+ tcp.Write("tcp-msg-1")
+ time.Sleep(time.Millisecond * 50) // 等待协程发送数据
+
+ // 关闭连接和服务器
+ l.Close()
+ (tcp.(*tcpSender)).conn.Close()
+
+ // 发送消息,此数据会失败
+ tcp.Write("tcp-msg-2")
+ // time.Sleep(time.Millisecond * 50)
+
+ // 保存数据
+ tcp.Close()
+
+ // 重启,检查是否重发tcp-msg-2
+ l = server("127.0.0.1:9559")
+ tcp, err = NewTCPSender("./test_tcp", "127.0.0.1:9559")
+ if err != nil {
+ t.Error(err)
+ }
+
+ time.Sleep(time.Second * 2)
+
+ if string(tcp_recv_msg) != "tcp-msg-1tcp-msg-2" {
+ t.Error("message error. got " + string(tcp_recv_msg))
+ } else {
+ fmt.Println("TCP OK")
+ }
+
+ tcp.Close()
+ l.Close()
+}
diff --git a/.svn/pristine/43/43f852c1515a55d48e5d25081f9210b9da4ff66c.svn-base b/.svn/pristine/43/43f852c1515a55d48e5d25081f9210b9da4ff66c.svn-base
new file mode 100644
index 0000000..c119522
--- /dev/null
+++ b/.svn/pristine/43/43f852c1515a55d48e5d25081f9210b9da4ff66c.svn-base
@@ -0,0 +1,35 @@
+package esLogUtil
+
+import (
+ "testing"
+ "time"
+)
+
+func TestWrite(t *testing.T) {
+ Start("http://10.1.0.86:9200", "dzg_gs_log_gmc2", 20008)
+ for i := 0; i < 10000; i++ {
+ InfoLog("ES在线日志测试")
+ WarnLog("ES在线日志测试")
+ DebugLog("ES在线日志测试")
+ ErrorLog("ES在线日志测试")
+ FatalLog("ES在线日志测试")
+ }
+ Stop()
+}
+
+func BenchmarkWrite(b *testing.B) {
+ Start("http://106.52.100.147:14001", "20008_gs_log", 20008)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ InfoLog("ES在线日志测试%d", i)
+ WarnLog("ES在线日志测试%d", i)
+ DebugLog("ES在线日志测试%d", i)
+ ErrorLog("ES在线日志测试%d", i)
+ FatalLog("ES在线日志测试%d", i)
+ }
+ b.StopTimer()
+
+ time.Sleep(30 * time.Second)
+ Stop()
+}
diff --git a/.svn/pristine/44/441ecb83b8c1a3af9e234f21ac76c082a4f9ff7b.svn-base b/.svn/pristine/44/441ecb83b8c1a3af9e234f21ac76c082a4f9ff7b.svn-base
new file mode 100644
index 0000000..47fa1a1
--- /dev/null
+++ b/.svn/pristine/44/441ecb83b8c1a3af9e234f21ac76c082a4f9ff7b.svn-base
@@ -0,0 +1,33 @@
+package gameServerMgr
+
+import (
+ "encoding/json"
+
+ . "Framework/managecenterModel"
+)
+
+var (
+ mChargeConfigMap = make(map[int32][]*ChargeConfig, 0)
+)
+
+//解析充值配置信息
+func ParseChargeConfigInfo(partnerList []*Partner) {
+ tmpChargeConfigMap := make(map[int32][]*ChargeConfig, 0)
+
+ //循环解析所有合作商里面的充值配置信息
+ for _, partner := range partnerList {
+ var chargeConfigList []*ChargeConfig
+ if err := json.Unmarshal([]byte(partner.ChargeConfig), &chargeConfigList); err == nil {
+ tmpChargeConfigMap[partner.Id] = chargeConfigList
+ }
+ }
+
+ mChargeConfigMap = tmpChargeConfigMap
+}
+
+// 根据合作商Id获取合作商充值配置对象
+func GetChargeConfigList(partnerId int32) (chargeConfigList []*ChargeConfig, exist bool) {
+ chargeConfigList, exist = mChargeConfigMap[partnerId]
+
+ return
+}
diff --git a/.svn/pristine/44/4455e0cfdc1b824c9dcb29ac73ba4313e7b94906.svn-base b/.svn/pristine/44/4455e0cfdc1b824c9dcb29ac73ba4313e7b94906.svn-base
new file mode 100644
index 0000000..071d1a4
--- /dev/null
+++ b/.svn/pristine/44/4455e0cfdc1b824c9dcb29ac73ba4313e7b94906.svn-base
@@ -0,0 +1,47 @@
+package debugUtil
+
+import "github.com/fatih/color"
+
+// Code 显示代码
+type Code = color.Attribute
+
+const (
+ Code_Reset Code = color.Reset
+ Code_Bold Code = color.Bold
+ Code_Faint Code = color.Faint
+ Code_Italic Code = color.Italic
+ Code_Underline Code = color.Underline
+ Code_BlinkSlow Code = color.BlinkSlow
+ Code_BlinkRapid Code = color.BlinkRapid
+ Code_ReverseVideo Code = color.ReverseVideo
+ Code_Concealed Code = color.Concealed
+ Code_CrossedOut Code = color.CrossedOut
+)
+
+// ForegroundColor 前景色
+type ForegroundColor = color.Attribute
+
+const (
+ Foreground_Black ForegroundColor = color.FgBlack
+ Foreground_Red ForegroundColor = color.FgRed
+ Foreground_Green ForegroundColor = color.FgGreen
+ Foreground_Yellow ForegroundColor = color.FgYellow
+ Foreground_Blue ForegroundColor = color.FgBlue
+ Foreground_Purple ForegroundColor = color.FgMagenta
+ Foreground_Cyan ForegroundColor = color.FgCyan
+ Foreground_White ForegroundColor = color.FgWhite
+)
+
+// BackgroundColor 背景色
+type BackgroundColor = color.Attribute
+
+const (
+ BackgroundColor_Black = color.BgBlack
+ BackgroundColor_Red = color.BgRed
+ BackgroundColor_Green = color.BgGreen
+ BackgroundColor_Yellow = color.BgYellow
+ BackgroundColor_Blue = color.BgBlue
+ BackgroundColor_Purple = color.BgMagenta
+ BackgroundColor_Cyan = color.BgCyan
+ BackgroundColor_White = color.BgWhite
+)
diff --git a/.svn/pristine/44/4472e6a7a56519f9549a2f2f3f364207e68b78bb.svn-base b/.svn/pristine/44/4472e6a7a56519f9549a2f2f3f364207e68b78bb.svn-base
new file mode 100644
index 0000000..fa84949
--- /dev/null
+++ b/.svn/pristine/44/4472e6a7a56519f9549a2f2f3f364207e68b78bb.svn-base
@@ -0,0 +1,98 @@
+package hash32
+
+/*
+ * ***注意***
+ *
+ * Sum 使用的是[]byte参数;string中文是utf-8编码
+ * SumByRune 使用的是[]rune参数;中文使用的是unicode编码
+ *
+ * 两种参数中文编码不同;同一个string调用两个接口得到的hash是不同的!!! 这是要特别注意的
+ *
+ * 对string进行for range操作会自动被[]rune化;一定要注意!!!
+ *
+ */
+
+const shiftBit = 11 // 每个字节移位数(测试经验值11)
+const reverseBit = 32 - shiftBit
+
+// 快速Hash计算(*** 注意:只取了rune低16位进行hash计算;计算结果与SumByRune不一致 ***)
+func FastSumByRune2(in rune, hs uint32) (out uint32) {
+ out = ((hs << shiftBit) | (hs >> reverseBit)) + uint32(byte(in>>8))
+ out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in))
+ return
+}
+
+// 快速Hash计算(*** 此计算结果与SumByRune一致 ***)
+func FastSumByRune4(in rune, hs uint32) (out uint32) {
+ out = ((hs << shiftBit) | (hs >> reverseBit)) + uint32(byte(in>>24))
+ out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in>>16))
+ out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in>>8))
+ out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in))
+ return
+}
+
+// 原Hash值参数重
+func hsArg(hsOpt ...uint32) (out uint32) {
+ out = uint32(0)
+ if len(hsOpt) > 0 {
+ out = hsOpt[0]
+ }
+ return
+}
+
+// Hash计算
+// in - 待hash串
+// hsOpt - 原hash值(在此基础上继续hash)
+func Sum(in []byte, hsOpt ...uint32) (out uint32) {
+ out = hsArg(hsOpt...)
+ for _, v := range in {
+ out = ((out << shiftBit) | (out >> reverseBit)) + uint32(v)
+ }
+
+ return
+}
+
+// Hash计算
+func SumByRune(in rune, hsOpt ...uint32) (out uint32) {
+ // rune转[]byte
+ inVal := make([]byte, 4)
+ inVal[0] = byte(in >> 24)
+ inVal[1] = byte(in >> 16)
+ inVal[2] = byte(in >> 8)
+ inVal[3] = byte(in)
+
+ // *** 经实际测试:不加以下代码运行效率更高 ***
+
+ // 去除前面多余的\x00
+ // for {
+ // if len(inVal) <= 1 {
+ // // 以免全0异常;至少要保留1位
+ // break
+ // }
+ // if inVal[0] == 0 {
+ // inVal = inVal[1:]
+ // } else {
+ // break
+ // }
+ // }
+ // 规避hash冲突,如:"N-"与"中"unicode编码均为#4E2D,即会产生hash冲突
+ // 若长度>1(即非常规ASCII),所有字节最高位置1
+ // if len(inVal) > 1 {
+ // for i := 0; i < len(inVal); i++ {
+ // inVal[i] |= 0x80
+ // }
+ // }
+ out = Sum(inVal, hsOpt...)
+
+ return
+}
+
+// Hash计算
+func SumByRunes(in []rune, hsOpt ...uint32) (out uint32) {
+ out = hsArg(hsOpt...)
+ for _, v := range in {
+ out = SumByRune(v, out)
+ }
+
+ return
+}
diff --git a/.svn/pristine/45/452216f78217ea55998820ec3ca6c0e9ae15c4f0.svn-base b/.svn/pristine/45/452216f78217ea55998820ec3ca6c0e9ae15c4f0.svn-base
new file mode 100644
index 0000000..54b794f
--- /dev/null
+++ b/.svn/pristine/45/452216f78217ea55998820ec3ca6c0e9ae15c4f0.svn-base
@@ -0,0 +1,3 @@
+DefaultLogPath/
+
+/test_*/
diff --git a/.svn/pristine/45/454997784756d5cf8e2dd0c2ef3ccb48f3739826.svn-base b/.svn/pristine/45/454997784756d5cf8e2dd0c2ef3ccb48f3739826.svn-base
new file mode 100644
index 0000000..503ebf7
--- /dev/null
+++ b/.svn/pristine/45/454997784756d5cf8e2dd0c2ef3ccb48f3739826.svn-base
@@ -0,0 +1,103 @@
+package ini_config
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+)
+
+// ParseFile
+// @description: 从文件读取配置文件,并转化为map对象
+// parameter:
+// @filePath:文件路径
+// return:
+// @map[string]string: 配置信息
+// @error:错误信息
+func ParseFile(filePath string) (map[string]string, error) {
+ fn, err := os.Open(filePath)
+ if err != nil {
+ panic(err)
+ }
+ defer fn.Close()
+
+ kvMap := make(map[string]string)
+ rd := bufio.NewReader(fn)
+ for {
+ data, _, err := rd.ReadLine()
+ if err != nil || io.EOF == err {
+ break
+ }
+
+ line := strings.TrimSpace(string(data))
+ if line == "" || line[0:1] == "#" {
+ continue
+ }
+
+ var k string
+ var v string
+ k, v, err = Parse(line)
+ if err != nil {
+ return nil, err
+ }
+
+ kvMap[k] = v
+ }
+
+ return kvMap, nil
+}
+
+// Parse
+// @description: 转换单行字符串为配置对象
+// parameter:
+// @line:单行内容
+// return:
+// @string:key
+// @string:value
+// @error:错误信息
+func Parse(line string) (string, string, error) {
+ ls := strings.SplitN(line, "=", 2)
+ if len(ls) != 2 {
+ return "", "", errors.New(fmt.Sprintf("配置%s中未找到=分隔符", line))
+ }
+
+ var key = strings.TrimSpace(ls[0])
+ var value string
+
+ i := strings.LastIndex(ls[1], "#")
+ if i < 0 {
+ value = strings.TrimSpace(ls[1])
+ } else {
+ s := ls[1][:i]
+ value = strings.TrimSpace(s)
+ }
+
+ return key, value, nil
+}
+
+// ParseMultipleLines
+// @description: 转换多行字符串为配置对象
+// parameter:
+// @content:多行内容(通过\n换行)
+// return:
+// @map[string]string:配置信息
+// @error:错误信息
+func ParseMultipleLines(content string) (map[string]string, error) {
+ lines := strings.Split(content, "\n")
+ kvMap := make(map[string]string)
+ for _, line := range lines {
+ if line == "" || line[0:1] == "#" {
+ continue
+ }
+
+ k, v, err := Parse(line)
+ if err != nil {
+ return nil, err
+ }
+ kvMap[k] = v
+ }
+
+ return kvMap, nil
+}
diff --git a/.svn/pristine/45/45a09743370b259aefd77d242d38fd7769811a8d.svn-base b/.svn/pristine/45/45a09743370b259aefd77d242d38fd7769811a8d.svn-base
new file mode 100644
index 0000000..6480a8d
--- /dev/null
+++ b/.svn/pristine/45/45a09743370b259aefd77d242d38fd7769811a8d.svn-base
@@ -0,0 +1,102 @@
+package timeUtil
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// 将字符串转换为标准的时间格式
+// str:输入,格式为:2015-10-25T17:07:30
+// 返回值:
+// 标准时间格式对象
+// 错误对象
+func ConverToStandardFormat(str string) (result time.Time, err error) {
+ newStr := strings.Replace(str, "T", ":", -1)
+ newStr = strings.Replace(newStr, "-", ":", -1)
+ newStr = strings.Replace(newStr, ".", ":", -1)
+
+ slice := strings.Split(newStr, ":")
+ slice = slice[:6] // 只取前6位(表示年-月-日 时:分:秒)
+
+ intSlice := make([]int, len(slice))
+ for index, item := range slice {
+ if intItem, err1 := strconv.Atoi(item); err1 != nil {
+ err = fmt.Errorf("输入字符串的格式错误:%s,转换后的格式为:%s", str, newStr)
+ return
+ } else {
+ intSlice[index] = intItem
+ }
+ }
+
+ result = time.Date(intSlice[0], time.Month(intSlice[1]), intSlice[2], intSlice[3], intSlice[4], intSlice[5], 0, time.Local)
+ return
+}
+
+// 将时间转换为int类型(20160120,共8位)
+// t:时间
+// 返回值:
+// int类型的数字
+func ConvertToInt(t time.Time) int {
+ year := int(t.Year())
+ month := int(t.Month())
+ day := int(t.Day())
+
+ return year*10e3 + month*10e1 + day
+}
+
+// 计算两个时间的日期差值
+func SubDay(time1, time2 time.Time) int {
+ // 当前时间距离00:00:00的秒数
+ awayFromZero := func(val time.Time) int64 {
+ hour := val.Hour()
+ minute := val.Minute()
+ second := val.Second()
+ return int64(hour*3600 + minute*60 + second)
+ }
+
+ // 每天对应的秒数
+ var eachDaySecond int64 = 24 * 3600
+
+ // 计算出两个时间对应的00:00:00时的时间戳
+ unix1 := time1.Unix() - awayFromZero(time1)
+ unix2 := time2.Unix() - awayFromZero(time2)
+
+ if unix1 < unix2 {
+ return int((unix2 - unix1) / eachDaySecond)
+ } else {
+ return int((unix1 - unix2) / eachDaySecond)
+ }
+}
+
+// 解析时间字符串,要求时间格式形式为:12:59:59 这种形式
+// timeStr:时间字符串
+// 返回值:
+// err:错误信息
+// hour:小时值
+// minute:分钟值
+// second:秒数
+func ParseTimeString(timeStr string) (err error, hour int, minute int, second int) {
+ timeSlice := strings.Split(timeStr, ":")
+ if len(timeSlice) != 3 {
+ err = fmt.Errorf("时间字符串格式不正确:%v", timeStr)
+ return
+ }
+
+ hour, _ = strconv.Atoi(timeSlice[0])
+ minute, _ = strconv.Atoi(timeSlice[1])
+ second, _ = strconv.Atoi(timeSlice[2])
+
+ return
+}
+
+// 获取时间的日期值
+// timeVal:时间值
+// 返回值:
+// time.Time:日期值
+func GetDate(timeVal time.Time) time.Time {
+ year, month, day := timeVal.Date()
+
+ return time.Date(year, month, day, 0, 0, 0, 0, timeVal.Location())
+}
diff --git a/.svn/pristine/45/45b8bbbab2a9efeb7b70840597892f85147de079.svn-base b/.svn/pristine/45/45b8bbbab2a9efeb7b70840597892f85147de079.svn-base
new file mode 100644
index 0000000..7df92b0
--- /dev/null
+++ b/.svn/pristine/45/45b8bbbab2a9efeb7b70840597892f85147de079.svn-base
@@ -0,0 +1,208 @@
+package monitorMgr
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "goutil/debugUtil"
+ "goutil/logUtil"
+ "goutil/webUtil"
+)
+
+var (
+ // 报告监控信息的URL
+ remoteURL = "http://maintenance.7qule.com/Manage/Monitor.ashx"
+
+ // 服务器IP
+ serverIP string
+
+ // 服务器名称
+ serverName string
+
+ // 监控时间间隔(单位:分钟)
+ monitorInterval = 5
+
+ // 重复消息发送的时间间隔(单位:分钟)
+ duplicateInterval = 5
+
+ // 已经发送的消息
+ sentMessageMap = make(map[string]int64)
+
+ // 已经发送消息的锁对象
+ sentMessageMutex sync.Mutex
+
+ // 监控方法列表
+ monitorFuncList = make([]func() error, 0, 4)
+
+ // 监控方法锁对象
+ monitorFuncMutex sync.Mutex
+)
+
+// SetURL ...设置监控信息发送的URL
+// url:监控信息发送的URL
+func SetURL(url string) {
+ remoteURL = url
+}
+
+// SetDuplicateInterval ...设置重复消息发送的时间间隔(单位:分钟)
+// _duplicateInterval:重复消息发送的时间间隔(单位:分钟)
+func SetDuplicateInterval(_duplicateInterval int) {
+ duplicateInterval = _duplicateInterval
+}
+
+// SetParam ...设置参数
+// _serverIP:服务器IP
+// _serverName:服务器名称
+// _monitorInterval:监控时间间隔(单位:分钟)
+func SetParam(_serverIP, _serverName string, _monitorInterval int) {
+ serverIP = _serverIP
+ serverName = _serverName
+ monitorInterval = _monitorInterval
+}
+
+// RegisterMonitorFunc ...注册监控方法
+// f:监控方法
+func RegisterMonitorFunc(f func() error) {
+ monitorFuncMutex.Lock()
+ defer monitorFuncMutex.Unlock()
+
+ monitorFuncList = append(monitorFuncList, f)
+}
+
+// Start ...启动监控服务(obsolete,建议使用Start2)
+// serverIp:服务器IP
+// serverName:服务器名称
+// monitorInterval:监控时间间隔(单位:分钟)
+func Start(serverIp, serverName string, monitorInterval int) {
+ monitorConfig := NewMonitorConfig(serverIp, serverName, monitorInterval)
+ Start2(monitorConfig)
+}
+
+// Start ...启动监控服务2
+// monitorConfig:监控配置对象
+func Start2(monitorConfig *MonitorConfig) {
+ // 设置参数
+ SetParam(monitorConfig.ServerIp, monitorConfig.ServerName, monitorConfig.Interval)
+
+ // 实际的监控方法调用
+ monitorFunc := func() {
+ monitorFuncMutex.Lock()
+ defer monitorFuncMutex.Unlock()
+
+ for _, item := range monitorFuncList {
+ if err := item(); err != nil {
+ Report(err.Error())
+ }
+ }
+ }
+
+ go func() {
+ // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃
+ defer func() {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+ }
+ }()
+
+ for {
+ // 先休眠,避免系统启动时就进行报警
+ time.Sleep(time.Minute * time.Duration(monitorInterval))
+
+ // 实际的监控方法调用
+ monitorFunc()
+ }
+ }()
+}
+
+// 判断指定时间内是否已经处理过
+// conent:报告内容
+func isDuplicate(content string) bool {
+ if ts, exists := sentMessageMap[content]; exists && time.Now().Unix()-ts < int64(60*duplicateInterval) {
+ return true
+ }
+
+ return false
+}
+
+// 添加到已发送集合中
+// conent:报告内容
+func addToMap(content string) {
+ sentMessageMap[content] = time.Now().Unix()
+}
+
+// Report ...报告异常信息
+// format:报告内容格式
+// args:具体参数
+func Report(format string, args ...interface{}) {
+ if len(args) <= 0 {
+ Report2(format, "")
+ } else {
+ Report2(fmt.Sprintf(format, args...), "")
+ }
+}
+
+// Report ...报告异常信息
+// title:上报的标题
+// contentFmt:报告内容
+// args:参数列表
+func Report2(title, contentFmt string, args ...interface{}) {
+ content := contentFmt
+ if len(args) > 0 {
+ content = fmt.Sprintf(contentFmt, args...)
+ }
+
+ sentMessageMutex.Lock()
+ defer sentMessageMutex.Unlock()
+
+ // 判断指定时间内是否已经处理过
+ if isDuplicate(title) {
+ return
+ }
+
+ logUtil.WarnLog(fmt.Sprintf("MonitorReport:ServerIP:%s,ServerName:%s,Title:%s Content:%s", serverIP, serverName, title, content))
+
+ // 判断是否是DEBUG模式
+ if debugUtil.IsDebug() {
+ return
+ }
+
+ detailMsg := title
+ if len(content) > 0 {
+ detailMsg = fmt.Sprintf("Title:%s Content:%s", title, content)
+ }
+
+ // 定义请求参数
+ postDict := make(map[string]string)
+ postDict["ServerIp"] = serverIP
+ postDict["ServerName"] = serverName
+ postDict["Content"] = detailMsg
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err := webUtil.PostMapData(remoteURL, postDict, header, transport)
+ // 连接服务器,以获取数据
+ //returnBytes, err := webUtil.PostWebData(remoteURL, postDict, nil)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("MonitorReport:,错误信息为:%s", err))
+ return
+ }
+ if statusCode != 200 {
+ logUtil.ErrorLog(fmt.Sprintf("MonitorReport:,状态吗为:%d", statusCode))
+ return
+ }
+
+ result := string(returnBytes)
+ logUtil.WarnLog(fmt.Sprintf("MonitorReport:Result:%s", result))
+
+ if result != "200" {
+ logUtil.ErrorLog(fmt.Sprintf("返回值不正确,当前返回值为:%s", result))
+ }
+
+ // 添加到已发送集合中
+ addToMap(title)
+}
diff --git a/.svn/pristine/45/45f0c43c59968de8708cb631ec180d949e04a2d8.svn-base b/.svn/pristine/45/45f0c43c59968de8708cb631ec180d949e04a2d8.svn-base
new file mode 100644
index 0000000..0314033
--- /dev/null
+++ b/.svn/pristine/45/45f0c43c59968de8708cb631ec180d949e04a2d8.svn-base
@@ -0,0 +1,186 @@
+package logSqlSync
+
+import (
+ "database/sql"
+ "fmt"
+ "time"
+
+ "goutil/logUtil"
+)
+
+// 同步信息表是否已经被初始化
+var ifSyncingTableInited bool = false
+
+// 同步信息项,保存已经处理过的文件的信息
+type syncingModel struct {
+ // 服务器组Id
+ ServerGroupId int32
+
+ // 待处理文件的绝对路径
+ FilePath string
+
+ // 待处理文件的偏移量
+ FileOffset int64
+
+ // 更新时间
+ UpdateTime time.Time
+}
+
+// 同步信息对象
+type syncingInfo struct {
+ // 服务器组Id
+ ServerGroupId int32
+
+ // 同步信息项
+ item *syncingModel
+
+ // 数据库连接对象
+ db *sql.DB
+}
+
+// 获取同步信息
+// filePath:正在同步的文件
+// fileOffset:同步到的位置
+func (this *syncingInfo) GetSyncingInfo() (filePath string, fileOffset int64) {
+ return this.item.FilePath, this.item.FileOffset
+}
+
+// 更新正在同步的位置和文件信息
+// filePath:文件路径
+// offset:当前同步到的位置
+// tran:事务对象,可以为nil
+// 返回值:
+// error:处理的错误信息
+func (this *syncingInfo) Update(filePath string, offset int64, tran *sql.Tx) error {
+ this.item.FilePath = filePath
+ this.item.FileOffset = offset
+ this.item.UpdateTime = time.Now()
+
+ // 更新到数据库
+ return this.update(this.item, tran)
+}
+
+// 初始化同步信息
+// 返回值:
+// error:错误信息
+func (this *syncingInfo) init() error {
+ // 数据表初始化
+ if ifSyncingTableInited == false {
+ if err := this.initSyncingInfoTable(this.db); err == nil {
+ ifSyncingTableInited = true
+ } else {
+ return err
+ }
+ }
+
+ // 获取此表的同步信息
+ data, exist, err := this.get()
+ if err != nil {
+ return err
+ }
+
+ // 2. 如果同步信息不存在,则初始化一条到此表
+ if exist == false {
+ data = &syncingModel{
+ ServerGroupId: this.ServerGroupId,
+ FilePath: "",
+ FileOffset: 0,
+ UpdateTime: time.Now(),
+ }
+ }
+
+ this.item = data
+ return nil
+}
+
+// 初始化同步信息表结构
+// db:数据库连接对象
+func (this *syncingInfo) initSyncingInfoTable(db *sql.DB) error {
+ // 创建同步信息表
+ createTableSql := `CREATE TABLE IF NOT EXISTS syncing_info (
+ ServerGroupId int NOT NULL COMMENT '服务器组Id',
+ FilePath varchar(500) NOT NULL COMMENT '正在同步的文件路径',
+ FileOffset bigint(20) NOT NULL COMMENT '偏移量',
+ UpdateTime datetime NOT NULL COMMENT '最后一次更新时间',
+ PRIMARY KEY (ServerGroupId)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='正在同步的文件信息';`
+ if _, err := db.Exec(createTableSql); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.initSyncingInfoTable Error:%s", err.Error()))
+ return err
+ }
+
+ return nil
+}
+
+// 从数据库获取数据
+// 返回值:
+// data:获取到的数据
+// exist:是否存在此数据
+// err:错误信息
+func (this *syncingInfo) get() (data *syncingModel, exist bool, err error) {
+ //// 从数据库查询
+ querySql := fmt.Sprintf("SELECT FilePath,FileOffset,UpdateTime FROM syncing_info WHERE ServerGroupId ='%v'", this.ServerGroupId)
+ var rows *sql.Rows
+ rows, err = this.db.Query(querySql)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
+ return
+ }
+ defer rows.Close()
+
+ if rows.Next() == false {
+ exist = false
+ return
+ }
+ exist = true
+
+ // 读取数据
+ data = &syncingModel{
+ ServerGroupId: this.ServerGroupId,
+ }
+ err = rows.Scan(&data.FilePath, &data.FileOffset, &data.UpdateTime)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
+ return
+ }
+
+ return
+}
+
+// 把同步信息更新到数据库
+// data:待更新的数据
+// tran:事务处理对象
+// 返回值:
+// error:错误信息
+func (this *syncingInfo) update(data *syncingModel, tran *sql.Tx) error {
+ updateSql := "REPLACE INTO `syncing_info` SET `ServerGroupId` = ?, `FilePath` = ?,`FileOffset` = ?, `UpdateTime` = ?;"
+ var err error
+ if tran != nil {
+ _, err = tran.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
+ } else {
+ _, err = this.db.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
+ }
+
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.update ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
+ }
+
+ return err
+}
+
+// 创建同步信息对象
+// _dirPath:目录的路径
+// _identifier:当前数据的唯一标识(可以使用数据库表名)
+// _db:数据库连接对象
+// 返回值:
+// 同步信息对象
+func newSyncingInfoObject(serverGroupId int32, _db *sql.DB) (result *syncingInfo, err error) {
+ result = &syncingInfo{
+ ServerGroupId: serverGroupId,
+ db: _db,
+ }
+
+ err = result.init()
+
+ return result, err
+}
diff --git a/.svn/pristine/46/460e1ba3b9bd0b80cd60485a6013941777b27d7f.svn-base b/.svn/pristine/46/460e1ba3b9bd0b80cd60485a6013941777b27d7f.svn-base
new file mode 100644
index 0000000..1ddcb42
--- /dev/null
+++ b/.svn/pristine/46/460e1ba3b9bd0b80cd60485a6013941777b27d7f.svn-base
@@ -0,0 +1,47 @@
+package coroutine_timer
+
+const (
+ // 添加
+ cmd_add = 1
+
+ // 删除
+ cmd_del = 2
+)
+
+// cmdModel
+// @description: 命令对象
+type cmdModel struct {
+ // cmd 指令
+ cmd int
+
+ // paramObj 指令参数
+ paramObj interface{}
+
+ // resObj 指令返回对象
+ resObj interface{}
+
+ // err 指令返回的错误
+ err error
+
+ // waitChan 等待channel
+ waitChan chan struct{}
+}
+
+// newCmdModel
+// @description: 创建cmd模型对象
+// parameter:
+// @c:cmd命令
+// @po:参数
+// return:
+// @*cmdModel:
+func newCmdModel(c int, po interface{}) *cmdModel {
+ result := &cmdModel{
+ cmd: c,
+ paramObj: po,
+ resObj: nil,
+ err: nil,
+ waitChan: make(chan struct{}, 1),
+ }
+
+ return result
+}
diff --git a/.svn/pristine/46/462e834bc4c52b9546cd5900c63f09387213c2e5.svn-base b/.svn/pristine/46/462e834bc4c52b9546cd5900c63f09387213c2e5.svn-base
new file mode 100644
index 0000000..8bbc616
--- /dev/null
+++ b/.svn/pristine/46/462e834bc4c52b9546cd5900c63f09387213c2e5.svn-base
@@ -0,0 +1,166 @@
+package gameServerMgr
+
+import (
+ "fmt"
+
+ . "Framework/managecenterModel"
+)
+
+var (
+ mServerMap = make(map[int32][]*Server, 0)
+)
+
+//合作商、服务器组合列表
+type PartnerServer struct {
+ //合作商Id
+ mPartnerId int32
+
+ //服务器Id
+ mServerId int32
+}
+
+//解析服务器信息
+func ParseServerInfo(serverList []*Server) {
+ tempServerMap := make(map[int32][]*Server, 0)
+ for _, server := range serverList {
+ _, exist := tempServerMap[server.PartnerId]
+ if !exist {
+ tempServerMap[server.PartnerId] = make([]*Server, 0)
+ }
+ tempServerMap[server.PartnerId] = append(tempServerMap[server.PartnerId], server)
+ }
+ mServerMap = tempServerMap
+}
+
+//获取服务器对象
+func GetServerItem(partnerId, serverId int32) (server *Server, exist bool) {
+ serverList, existServer := mServerMap[partnerId]
+ if !existServer {
+ return
+ }
+ for _, serverItem := range serverList {
+ if serverItem.Id == serverId {
+ server = serverItem
+ exist = true
+ break
+ }
+ }
+ return
+}
+
+//判断服务器是否存在
+func IfServerExists(partnerId, serverId int32) (exists bool) {
+ _, exists = GetPartnerItem(partnerId)
+ if !exists {
+ return
+ }
+ _, exists = GetServerItem(partnerId, serverId)
+ if !exists {
+ return
+ }
+
+ return
+}
+
+//获取服务器名称
+func GetServerName(partnerId, serverId int32) (serverName string) {
+ _, existPartner := GetPartnerItem(partnerId)
+ if !existPartner {
+ return
+ }
+ server, existServer := GetServerItem(partnerId, serverId)
+ if !existServer {
+ return
+ }
+ serverName = server.Name
+
+ return
+}
+
+//检测是否有游戏版本更新
+func CheckNewGameVersion(partnerId, serverId, gameVersionId int32) (gameVersionUrl string, exist bool) {
+ server, existServer := GetServerItem(partnerId, serverId)
+ if !existServer {
+ exist = existServer
+ return
+ }
+
+ if gameVersionId < server.MinGameVersionId {
+ partner, existPartner := GetPartnerItem(partnerId)
+ if !existPartner {
+ exist = existPartner
+ return
+ }
+ exist = true
+ gameVersionUrl = partner.GameVersionUrl
+ }
+
+ return
+}
+
+//获取合作商、服务器的组合字符串
+//字符串格式:PartnerId_ServerId|PartnerId_ServerId|
+func GetPartnerServerPairString() (partnerServerPair string) {
+ for _, ps := range GetPartnerServerPairList() {
+ partnerServerPair += fmt.Sprintf("%d_%d|", ps.mPartnerId, ps.mServerId)
+ }
+ return
+}
+
+//获取合作商、服务器的组合列表
+func GetPartnerServerPairList() (partnerServerList []*PartnerServer) {
+ for key := range mServerMap {
+ for _, server := range mServerMap[key] {
+ if server.GroupId == GetServerGroup().Id {
+ var ps *PartnerServer = &PartnerServer{server.PartnerId, server.Id}
+ partnerServerList = append(partnerServerList, ps)
+ }
+ }
+ }
+
+ return
+}
+
+// // 获取合作商、服务器的组合字符串
+// // serverGroupId:服务器组Id
+// // 返回值
+// // 合作商、服务器的组合字符串
+// func (this *ManageCenterUtil) GetPartnerServerPairString(serverGroupId int32) string {
+// var buf bytes.Buffer
+
+// serverList := managecenterMgr.GetServerList(serverGroupId)
+// for _, item := range serverList {
+// buf.WriteString(fmt.Sprintf("%d_%d|", item.PartnerId, item.Id))
+// }
+
+// return buf.String()
+// }
+
+// // 是否是有效的合作商、服务器组合
+// // partnerId:合作商Id
+// // serverId:服务器Id
+// // parnterServerPairString:合作商、服务器的组合字符串,格式为:PartnerId_ServerId|PartnerId_ServerId|
+// // 返回值
+// // 是否有效
+// func (this *ManageCenterUtil) IfValidPartnerServerPair(partnerId, serverId int32, parnterServerPairString string) bool {
+// if parnterServerPairString == "" {
+// return false
+// }
+
+// partnerServerPairStringList := strings.Split(parnterServerPairString, "|")
+// if len(partnerServerPairStringList) == 0 {
+// return false
+// }
+
+// // 获得玩家的合作商、服务器组合字符串
+// partnerServerPair := fmt.Sprintf("%d_%d", partnerId, serverId)
+
+// // 遍历寻找
+// for _, item := range partnerServerPairStringList {
+// if item == partnerServerPair {
+// return true
+// }
+// }
+
+// return false
+// }
diff --git a/.svn/pristine/46/46fe9b43a26885328f556159b055b3d369732600.svn-base b/.svn/pristine/46/46fe9b43a26885328f556159b055b3d369732600.svn-base
new file mode 100644
index 0000000..a50f921
--- /dev/null
+++ b/.svn/pristine/46/46fe9b43a26885328f556159b055b3d369732600.svn-base
@@ -0,0 +1,16 @@
+package intUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+func Test1(t *testing.T) {
+ var originalNum int64 = 1234567891011121314
+ shuffledNum, err := ShuffleIntDigits(int64(originalNum))
+ if err != nil {
+ fmt.Println("Error:", err)
+ return
+ }
+ fmt.Printf("Original number: %d\nShuffled number: %d\n", originalNum, shuffledNum)
+}
diff --git a/.svn/pristine/47/47e1f67a37d3cf0affa5dd7f1a866f5375ac5629.svn-base b/.svn/pristine/47/47e1f67a37d3cf0affa5dd7f1a866f5375ac5629.svn-base
new file mode 100644
index 0000000..9f8eaa4
--- /dev/null
+++ b/.svn/pristine/47/47e1f67a37d3cf0affa5dd7f1a866f5375ac5629.svn-base
@@ -0,0 +1,71 @@
+package webServer
+
+import (
+ "net/http"
+
+ "goutil/typeUtil"
+)
+
+// webserver接口
+type IWebServer interface {
+ // 注册API
+ // path:注册的访问路径
+ // callback:回调方法
+ // configObj:Handler配置对象
+ RegisterHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
+
+ // 注册回调-增加用户自定义数据
+ RegisterHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{})
+
+ RegisterRegexHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
+
+ // 注册正则回调-增加用户自定义数据
+ RegisterRegexHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{})
+
+ // 设定Http Header信息
+ SetHeader(header map[string]string)
+
+ // 设定HTTP请求方法
+ SetMethod(method string)
+
+ // 设定当HTTP请求方法无效时,调用的处理器
+ SetInvalidMethodHandler(handler func(*Context))
+
+ // 设置WebServer请求是否经过了负载均衡中转
+ SetIfDelegate(ifDelegate bool)
+
+ // 设定默认页的处理器
+ SetDefaultPageHandler(handler func(*Context))
+
+ // 设定未找到指定的回调时的处理器
+ SetNotFoundPageHandler(handler func(*Context))
+
+ // 设置异常处理函数(默认只会记录在文件)
+ SetUnHandledPanicHandler(handler func(context *Context, errObj interface{}))
+
+ // 设定在Debug模式下是否需要验证IP地址
+ SetIfCheckIPWhenDebug(value bool)
+
+ // 设定当IP无效时调用的处理器
+ SetIPInvalidHandler(handler func(*Context))
+
+ // 设定用于检测参数是否有效的处理器
+ SetParamCheckHandler(handler func(typeUtil.MapData, []string, []string) ([]string, []string, bool))
+
+ // 设定当检测到参数无效时调用的处理器
+ SetParamInvalidHandler(handler func(*Context, []string, []string))
+
+ // 设定处理请求数据的处理器(例如压缩、解密等)
+ SetRequestDataHandler(handler func(*Context, []byte) ([]byte, error))
+
+ // 设定处理响应数据的处理器(例如压缩、加密等)
+ SetResponseDataHandler(handler func(*Context, []byte) ([]byte, error))
+
+ // 设定请求执行时间的处理器
+ SetExecuteTimeHandler(handler func(*Context))
+
+ // http应答处理
+ // responseWriter:应答对象
+ // request:请求对象
+ ServeHTTP(responseWriter http.ResponseWriter, request *http.Request)
+}
diff --git a/.svn/pristine/47/47e800dd36b3f0c082e6782f864014eb4e07d2a5.svn-base b/.svn/pristine/47/47e800dd36b3f0c082e6782f864014eb4e07d2a5.svn-base
new file mode 100644
index 0000000..94ae227
--- /dev/null
+++ b/.svn/pristine/47/47e800dd36b3f0c082e6782f864014eb4e07d2a5.svn-base
@@ -0,0 +1,1733 @@
+package redisUtil
+
+import (
+ "testing"
+ "time"
+)
+
+var (
+ redisPoolObj_string *RedisPool
+)
+
+func init() {
+ redisPoolObj_string = NewRedisPool("testPool", "10.1.0.21:6379", "redis_pwd", 5, 500, 200, 10*time.Second, 5*time.Second)
+}
+
+func TestSet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 对不存在的键进行设置:
+
+ redis> SET key "value"
+ OK
+ */
+
+ key := "key"
+ value := "value"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET key
+ "value"
+ */
+ got_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err := redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 对已存在的键进行设置:
+
+ redis> SET key "new-value"
+ OK
+ */
+ value = "new-value"
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET key
+ "new-value"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 使用 EX 选项:
+
+ redis> SET key-with-expire-time "hello" EX 10086
+ OK
+ */
+ key = "key-with-expire-time"
+ value = "hello"
+ successful, err = redisPoolObj_string.Set(key, value, "EX", 10086, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET key-with-expire-time
+ "hello"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", "key-with-expire-time")
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> TTL key-with-expire-time
+ (integer) 10069
+ */
+ ttl, exist, _, err := redisPoolObj_string.TTL(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't", key)
+ return
+ }
+ if ttl < 10086-5 {
+ t.Errorf("The TTL of key:%s is wrong. Now it's %d", key, ttl)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 使用 PX 选项:
+
+ redis> SET key-with-pexpire-time "moto" PX 123321
+ OK
+ */
+ key = "key-with-pexpire-time"
+ value = "moto"
+ successful, err = redisPoolObj_string.Set(key, value, "PX", 123321, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET key-with-pexpire-time
+ "moto"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> PTTL key-with-pexpire-time
+ (integer) 111939
+ */
+ ttl, exist, _, err = redisPoolObj_string.PTTL(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't", key)
+ return
+ }
+ if ttl < 123321-5000 {
+ t.Errorf("The TTL of key:%s is wrong. Now it's %d", key, ttl)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 使用 NX 选项:
+
+ redis> SET not-exists-key "value" NX
+ OK # 键不存在,设置成功
+ */
+ key = "not-exists-key"
+ value = "value"
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "NX")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET not-exists-key
+ "value"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET not-exists-key "new-value" NX
+ (nil) # 键已经存在,设置失败
+
+ */
+ newValue := "new-value"
+ successful, err = redisPoolObj_string.Set(key, newValue, "", 0, "NX")
+ if err != nil {
+ t.Fail()
+ }
+ if successful {
+ t.Errorf("Seting key:%s should fail, but now it doesn't.", key)
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GEt not-exists-key
+ "value" # 维持原值不变
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+
+ /*
+ 使用 XX 选项:
+
+ redis> EXISTS exists-key
+ (integer) 0
+ */
+ key = "exists-key"
+ value = "value"
+ exist, err = redisPoolObj_string.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("Key:%s should not exist, but now it does exist", key)
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET exists-key "value" XX
+ (nil) # 因为键不存在,设置失败
+ */
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "XX")
+ if err != nil {
+ t.Fail()
+ }
+ if successful {
+ t.Errorf("Seting key:%s should fail, but now it doesn't.", key)
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET exists-key "value"
+ OK # 先给键设置一个值
+ */
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Seting key:%s should succeed, but now it doesn't.", key)
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET exists-key "new-value" XX
+ OK # 设置新值成功
+ */
+ value = "new-value"
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "XX")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Seting key:%s should succeed, but now it doesn't.", key)
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET exists-key
+ "new-value"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET int-key 5
+ OK # 设置新值成功
+ */
+ key2 := "int-key"
+ value2 := 5
+ successful, err = redisPoolObj_string.Set(key2, value2, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Seting key:%s should succeed, but now it doesn't.", key)
+ }
+ deleteKeys = append(deleteKeys, key2)
+
+ /*
+ redis> GET int-key
+ 5
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got2, err := redisPoolObj_string.Int(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != value2 {
+ t.Errorf("Expected to get %d, but now got %d.", value2, got2)
+ return
+ }
+}
+
+func TestGet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 对不存在的键 key 或是字符串类型的键 key 执行 GET 命令:
+
+ redis> GET db
+ (nil)
+ */
+ key := "db"
+ _, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET db redis
+ OK
+ */
+ value := "redis"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET db
+ "redis"
+ */
+ got_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err := redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value {
+ t.Errorf("Expected to get %s, but now got %s.", value, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 对不是字符串类型的键 key 执行 GET 命令:
+
+ redis> DEL db
+ (integer) 1
+ */
+ count, err := redisPoolObj_string.Del(key)
+ if err != nil {
+ t.Fail()
+ }
+ if count != 1 {
+ t.Errorf("Expected to get 1, but now got %d", count)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> LPUSH db redis mongodb mysql
+ (integer) 3
+ */
+ _, err = redisPoolObj_string.LPush(key, "redis", "mongodb", "mysql")
+ if err != nil {
+ t.Fail()
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET db
+ (error) ERR Operation against a key holding the wrong kind of value
+ */
+ _, exist, err = redisPoolObj_string.Get(key)
+ if err == nil {
+ t.Fail()
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestGetSet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ redis> GETSET db mongodb # 没有旧值,返回 nil
+ (nil)
+ */
+ key := "db"
+ value1 := "mongodb"
+ got, exist, err := redisPoolObj_string.GetSet(key, value1)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("There should be no old value, but now there is.")
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET db
+ "mongodb"
+ */
+ got_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value1 {
+ t.Errorf("Expected to get %s, but now got %s.", value1, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETSET db redis # 返回旧值 mongodb
+ "mongodb"
+ */
+ value2 := "redis"
+ got_interface, exist, err = redisPoolObj_string.GetSet(key, value2)
+ if err != nil {
+ t.Fail()
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value1 {
+ t.Errorf("Expected to get %s, but now got %s.", value1, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET db
+ "redis"
+ */
+ got_interface, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err = redisPoolObj_string.String(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != value2 {
+ t.Errorf("Expected to get %s, but now got %s.", value2, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestStrLen(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 获取字符串值的长度:
+
+ redis> SET mykey "Hello world"
+ OK
+ */
+ key := "mykey"
+ value := "Hello world"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> STRLEN mykey
+ (integer) 11
+ 不存在的键的长度为 0 :
+ */
+ expectedLength := 11
+ got, err := redisPoolObj_string.StrLen(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expectedLength {
+ t.Errorf("Expected length %d, but got %d", expectedLength, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> STRLEN nonexisting
+ (integer) 0
+ */
+ key = "nonexisting"
+ expectedLength = 0
+ got, err = redisPoolObj_string.StrLen(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expectedLength {
+ t.Errorf("Expected length %d, but got %d", expectedLength, got)
+ return
+ }
+}
+
+func TestAppend(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 示例代码
+ 对不存在的 key 执行 APPEND :
+
+ redis> EXISTS myphone # 确保 myphone 不存在
+ (integer) 0
+ */
+ key := "myphone"
+ value := "value"
+ exist, err := redisPoolObj_string.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("Key:%s should not exist, but now it does exist", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> APPEND myphone "nokia" # 对不存在的 key 进行 APPEND ,等同于 SET myphone "nokia"
+ (integer) 5 # 字符长度
+ 对已存在的字符串进行 APPEND :
+ */
+ value = "nokia"
+ expected := 5
+ got, err := redisPoolObj_string.Append(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> APPEND myphone " - 1110" # 长度从 5 个字符增加到 12 个字符
+ (integer) 12
+ */
+ value = " - 1110"
+ expected = 12
+ got, err = redisPoolObj_string.Append(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET myphone
+ "nokia - 1110"
+ */
+ expected2 := "nokia - 1110"
+ got2_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("Key:%s should exist, but now it doesn't exist", key)
+ return
+ }
+ got2, err := redisPoolObj_string.String(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %s, but now got %s", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestSetRange(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 对非空字符串执行 SETRANGE 命令:
+
+ redis> SET greeting "hello world"
+ OK
+ */
+ key := "greeting"
+ value := "hello world"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SETRANGE greeting 6 "Redis"
+ (integer) 11
+ */
+ offset := 6
+ value = "Redis"
+ expected := 11
+ got, err := redisPoolObj_string.SetRange(key, offset, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET greeting
+ "hello Redis"
+ */
+ expected2 := "hello Redis"
+ got2_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got2, err := redisPoolObj_string.String(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %s, but now got %s", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 对空字符串/不存在的键执行 SETRANGE 命令:
+
+ redis> EXISTS empty_string
+ (integer) 0
+
+ redis> SETRANGE empty_string 5 "Redis!" # 对不存在的 key 使用 SETRANGE
+ (integer) 11
+
+ redis> GET empty_string # 空白处被"\x00"填充
+ "\x00\x00\x00\x00\x00Redis!"
+ */
+ key = "empty_string"
+ _, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ offset = 5
+ value = "Redis!"
+ expected3 := 11
+ got3, err := redisPoolObj_string.SetRange(key, offset, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d", expected3, got3)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ expected4 := "\x00\x00\x00\x00\x00Redis!"
+ got4_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got4, err := redisPoolObj_string.String(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected to get %s, but now got %s", expected4, got4)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestGetRange(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ redis> SET greeting "hello, my friend"
+ OK
+ */
+ key := "greeting"
+ value := "hello, my friend"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETRANGE greeting 0 4 # 返回索引0-4的字符,包括4。
+ "hello"
+ */
+ start, end := 0, 4
+ expected := "hello"
+ got, err := redisPoolObj_string.GetRange(key, start, end)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETRANGE greeting -1 -5 # 不支持回绕操作
+ ""
+ */
+ start, end = -1, -5
+ expected = ""
+ got, err = redisPoolObj_string.GetRange(key, start, end)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETRANGE greeting -3 -1 # 负数索引
+ "end"
+ */
+ start, end = -3, -1
+ expected = "end"
+ got, err = redisPoolObj_string.GetRange(key, start, end)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETRANGE greeting 0 -1 # 从第一个到最后一个
+ "hello, my friend"
+ */
+ start, end = 0, -1
+ expected = "hello, my friend"
+ got, err = redisPoolObj_string.GetRange(key, start, end)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GETRANGE greeting 0 1008611 # 值域范围不超过实际字符串,超过部分自动被符略
+ "hello, my friend"
+ */
+ start, end = 0, 1008611
+ expected = "hello, my friend"
+ got, err = redisPoolObj_string.GetRange(key, start, end)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestIncr(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ redis> SET page_view 20
+ OK
+ */
+ key := "page_view"
+ value := "20"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> INCR page_view
+ (integer) 21
+ */
+ expected := int64(21)
+ got, err := redisPoolObj_string.Incr(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET page_view # 数字值在 Redis 中以字符串的形式保存
+ "21"
+ */
+ expected2 := 21
+ got2_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got2, err := redisPoolObj_string.Int(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestIncrBy(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 键存在,并且值为数字:
+
+ redis> SET rank 50
+ OK
+
+ redis> INCRBY rank 20
+ (integer) 70
+
+ redis> GET rank
+ "70"
+ */
+ key := "rank"
+ value := "50"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ increment := int64(20)
+ expected := int64(70)
+ got, err := redisPoolObj_string.IncrBy(key, increment)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ expected2 := 70
+ got2_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got2, err := redisPoolObj_string.Int(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 键不存在:
+
+ redis> EXISTS counter
+ (integer) 0
+ */
+ key = "counter"
+ _, exist, err = redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> INCRBY counter 30
+ (integer) 30
+ */
+ increment = int64(30)
+ expected3 := int64(30)
+ got3, err := redisPoolObj_string.IncrBy(key, 30)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d", expected3, got3)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET counter
+ "30"
+ */
+ expected4 := 30
+ got4_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got4, err := redisPoolObj_string.Int(got4_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected to get %d, but now got %d", expected4, got4)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ 键存在,但值无法被解释为数字:
+
+ redis> SET book "long long ago..."
+ OK
+
+ redis> INCRBY book 200
+ (error) ERR value is not an integer or out of range
+ */
+ // This feature can't be tested, because the IncrBy function needs an int64 parameter.
+}
+
+func TestIncrByFloat(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ redis> GET decimal
+ "3.0"
+ */
+ key := "decimal"
+ value := "3.0"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ expected := 3.0
+ got_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got, err := redisPoolObj_string.Float64(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %f, but now got %f", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> INCRBYFLOAT decimal 2.56
+ "5.56"
+ */
+ increment := 2.56
+ expected2 := 5.56
+ got2, err := redisPoolObj_string.IncrByFloat(key, increment)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %f, but now got %f", expected2, got2)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> GET decimal
+ "5.56"
+ */
+ expected3 := 5.56
+ got3_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got3, err := redisPoolObj_string.Float64(got3_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %f, but now got %f", expected3, got3)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestDecrBy(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 对已经存在的键执行 DECRBY 命令:
+
+ redis> SET count 100
+ OK
+ */
+ key := "count"
+ value := 100
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> DECRBY count 20
+ (integer) 80
+ 对不存在的键执行 DECRBY 命令:
+ */
+ expected := int64(80)
+ decrement := int64(20)
+ got_interface, err := redisPoolObj_string.DecrBy(key, decrement)
+ if err != nil {
+ t.Fail()
+ }
+ got, err := redisPoolObj_string.Int64(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> EXISTS pages
+ (integer) 0
+ */
+ key = "pages"
+ exist, err := redisPoolObj_string.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> DECRBY pages 10
+ (integer) -10
+ */
+ expected = int64(-10)
+ decrement = int64(10)
+ got, err = redisPoolObj_string.DecrBy(key, decrement)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestMSet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 同时对多个键进行设置:
+
+ redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
+ OK
+ */
+ key_value_map := make(map[string]interface{})
+ key_value_map["date"] = "2012.3.30"
+ key_value_map["time"] = "11:00 a.m."
+ key_value_map["weather"] = "sunny"
+ err := redisPoolObj_string.MSet(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ /*
+ redis> MGET date time weather
+ 1) "2012.3.30"
+ 2) "11:00 a.m."
+ 3) "sunny"
+ */
+ keyList := make([]string, 0, len(key_value_map))
+ expected := make([]string, 0, len(key_value_map))
+ for k, v := range key_value_map {
+ keyList = append(keyList, k)
+ if v_str, ok := v.(string); ok {
+ expected = append(expected, v_str)
+ }
+ }
+ got_interface, err := redisPoolObj_string.MGet(keyList)
+ if err != nil {
+ t.Fail()
+ }
+ got, err := redisPoolObj_string.Strings(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoOrderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, keyList...)
+
+ /*
+ 覆盖已有的值:
+
+ redis> MGET k1 k2
+ 1) "hello"
+ 2) "world"
+ */
+ key_value_map = make(map[string]interface{})
+ key_value_map["k1"] = "hello"
+ key_value_map["k2"] = "world"
+ err = redisPoolObj_string.MSet(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ /*
+
+ redis> MSET k1 "good" k2 "bye"
+ OK
+ */
+ key_value_map["k1"] = "good"
+ key_value_map["k2"] = "bye"
+ err = redisPoolObj_string.MSet(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ /*
+ redis> MGET k1 k2
+ 1) "good"
+ 2) "bye"
+ */
+ keyList = make([]string, 0, len(key_value_map))
+ expected = make([]string, 0, len(key_value_map))
+ for k, v := range key_value_map {
+ keyList = append(keyList, k)
+ if v_str, ok := v.(string); ok {
+ expected = append(expected, v_str)
+ }
+ }
+
+ got_interface, err = redisPoolObj_string.MGet(keyList)
+ if err != nil {
+ t.Fail()
+ }
+ got, err = redisPoolObj_string.Strings(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoOrderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, keyList...)
+}
+
+func TestMSetNX(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ 对不存在的键执行 MSETNX 命令:
+
+ redis> MSETNX rmdbs "MySQL" nosql "MongoDB" key-value-store "redis"
+ (integer) 1
+ */
+ key_value_map := make(map[string]interface{})
+ key_value_map["rmdbs"] = "MySQL"
+ key_value_map["nosql"] = "MongoDB"
+ key_value_map["key-value-store"] = "redis"
+ successful, err := redisPoolObj_string.MSetNX(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("It should be successful, but now it's not.")
+ return
+ }
+
+ /*
+
+ redis> MGET rmdbs nosql key-value-store
+ 1) "MySQL"
+ 2) "MongoDB"
+ 3) "redis"
+ 对某个已经存在的键进行设置:
+ */
+ keyList := make([]string, 0, len(key_value_map))
+ expected := make([]string, 0, len(key_value_map))
+ for k, v := range key_value_map {
+ keyList = append(keyList, k)
+ if v_str, ok := v.(string); ok {
+ expected = append(expected, v_str)
+ }
+ }
+ got_interface, err := redisPoolObj_string.MGet(keyList)
+ if err != nil {
+ t.Fail()
+ }
+ got, err := redisPoolObj_string.Strings(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoOrderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, keyList...)
+
+ /*
+ redis> MSETNX rmdbs "Sqlite" language "python" # rmdbs 键已经存在,操作失败
+ (integer) 0
+ */
+ key_value_map = make(map[string]interface{})
+ key_value_map["rmdbs"] = "Sqlite"
+ key_value_map["language"] = "python"
+ successful, err = redisPoolObj_string.MSetNX(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+ if successful {
+ t.Errorf("It should be not successful, but now it is.")
+ return
+ }
+
+ /*
+ redis> EXISTS language # 因为 MSETNX 命令没有成功执行
+ (integer) 0 # 所以 language 键没有被设置
+ */
+ key := "language"
+ exist, err := redisPoolObj_string.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("The key:%s should not exist, but now it does.", key)
+ return
+ }
+
+ /*
+ redis> GET rmdbs # rmdbs 键也没有被修改
+ "MySQL"
+ */
+ key = "rmdbs"
+ expected2 := "MySQL"
+ got2_interface, exist, err := redisPoolObj_string.Get(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key)
+ return
+ }
+ got2, err := redisPoolObj_string.String(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %v, but got %v", expected2, got2)
+ return
+ }
+}
+
+func TestMGet(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ 代码示例
+ redis> SET redis redis.com
+ OK
+ */
+ key := "redis"
+ value := "redis.com"
+ successful, err := redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> SET mongodb mongodb.org
+ OK
+ */
+ key = "mongodb"
+ value = "mongodb.org"
+ successful, err = redisPoolObj_string.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set key:%s should be successful, but now it's not.", key)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ redis> MGET redis mongodb
+ 1) "redis.com"
+ 2) "mongodb.org"
+ */
+ keys := []string{"redis", "mongodb"}
+ expected := []string{"redis.com", "mongodb.org"}
+ got_interface, err := redisPoolObj_string.MGet(keys)
+ if err != nil {
+ t.Fail()
+ }
+ got, err := redisPoolObj_string.Strings(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoOrderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ return
+ }
+
+ /*
+ redis> MGET redis mongodb mysql # 不存在的 mysql 返回 nil
+ 1) "redis.com"
+ 2) "mongodb.org"
+ 3) (nil)
+ */
+ keys = []string{"redis", "mongodb", "mysql"}
+ expected = []string{"redis.com", "mongodb.org", ""}
+ got_interface, err = redisPoolObj_string.MGet(keys)
+ if err != nil {
+ t.Fail()
+ }
+ got, err = redisPoolObj_string.Strings(got_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoOrderedSliceEqual(got, expected) == false {
+ t.Errorf("Expected to get %v, but got %v", expected, got)
+ return
+ }
+}
diff --git a/.svn/pristine/48/48003ffa1a6493e340cfad0e3092a40126a4aece.svn-base b/.svn/pristine/48/48003ffa1a6493e340cfad0e3092a40126a4aece.svn-base
new file mode 100644
index 0000000..b0552a3
--- /dev/null
+++ b/.svn/pristine/48/48003ffa1a6493e340cfad0e3092a40126a4aece.svn-base
@@ -0,0 +1,43 @@
+package admin
+
+import (
+ "common/connection"
+ "goutil/logUtilPlus"
+)
+
+// AddAdmin 添加管理员
+// AddAdmin 添加新的管理员到数据库中。
+// 参数 admin: 包含管理员信息的对象。
+// 返回值: 插入操作影响的行数和可能发生的错误。
+func AddAdmin(admin *Admin) (int64, error) {
+
+ //处理一些验证
+
+ // 写入到数据库
+ result := connection.GetAdminDB().Create(&admin) // 通过数据的指针来创建
+
+ if result.Error != nil {
+ logUtilPlus.ErrorLog("添加管理员失败 错误信息:", result.Error.Error())
+ }
+ return admin.ID, nil
+}
+
+// GetAdminByID 根据管理员ID获取管理员信息
+func GetAdminByID(adminID int64) (*Admin, error) {
+ var admin Admin
+ result := connection.GetAdminDB().First(&admin, adminID)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+ return &admin, nil
+}
+
+// 管理员登录
+func Login(account string, password string) (*Admin, error) {
+ var admin Admin
+ result := connection.GetAdminDB().Where("account = ? AND password = ?", account, password).First(&admin)
+ if result.Error != nil {
+ return nil, result.Error
+ }
+ return &admin, nil
+}
diff --git a/.svn/pristine/48/4852aa2721098eea260b5d302d760e536bb7e64a.svn-base b/.svn/pristine/48/4852aa2721098eea260b5d302d760e536bb7e64a.svn-base
new file mode 100644
index 0000000..fc28df4
--- /dev/null
+++ b/.svn/pristine/48/4852aa2721098eea260b5d302d760e536bb7e64a.svn-base
@@ -0,0 +1,35 @@
+package impl_localfile
+
+import "sync"
+
+func (l *Logger) InfoLog(format string, args ...interface{}) {
+ l.log(getLog(format, args...), info, true)
+}
+
+func (l *Logger) WarnLog(format string, args ...interface{}) {
+ l.log(getLog(format, args...), warn, true)
+}
+
+func (l *Logger) DebugLog(format string, args ...interface{}) {
+ l.log(getLog(format, args...), debug, true)
+}
+
+func (l *Logger) ErrorLog(format string, args ...interface{}) {
+ l.log(getLog(format, args...), _error, true)
+}
+
+func (l *Logger) FatalLog(format string, args ...interface{}) {
+ l.log(getLog(format, args...), fatal, true)
+}
+
+func (l *Logger) CloseLog(waitFinish bool) {
+ wg := sync.WaitGroup{}
+
+ // 关闭所有的file
+ for _, logger := range l.loggerMap {
+ wg.Add(1)
+ go logger.Close(&wg, waitFinish)
+ }
+
+ wg.Wait()
+}
diff --git a/.svn/pristine/48/486e1cb4731af6df40aa03de3ed2ecdba22db264.svn-base b/.svn/pristine/48/486e1cb4731af6df40aa03de3ed2ecdba22db264.svn-base
new file mode 100644
index 0000000..13ca2b8
--- /dev/null
+++ b/.svn/pristine/48/486e1cb4731af6df40aa03de3ed2ecdba22db264.svn-base
@@ -0,0 +1,135 @@
+package configUtil
+
+import (
+ "fmt"
+ "testing"
+
+ "goutil/xmlUtil"
+)
+
+// bool值读取测试
+func TestBoolList(t *testing.T) {
+ xmlConfigData, errMsg := getxmlConfigListData()
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+
+ return
+ }
+
+ booList, errMsg := xmlConfigData.BoolList("html/body/ul/li/a", "id")
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+ return
+ }
+ fmt.Println("TestBoolList读取到的值:", booList)
+}
+
+// int值读取测试
+func TestIntList(t *testing.T) {
+ xmlConfigData, errMsg := getxmlConfigListData()
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+
+ return
+ }
+
+ valList, errMsg := xmlConfigData.IntList("html/body/ul/li/a", "id")
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+ return
+ }
+ fmt.Println("TestInt读取到的值:", valList)
+}
+
+// int64值读取测试
+func TestInt64List(t *testing.T) {
+ xmlConfigData, errMsg := getxmlConfigListData()
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+
+ return
+ }
+
+ valList, errMsg := xmlConfigData.Int64List("html/body/ul/li/a", "id")
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+ return
+ }
+ fmt.Println("TestInt64读取到的值:", valList)
+}
+
+// Float值读取测试
+func TestFloatList(t *testing.T) {
+ xmlConfigData, errMsg := getxmlConfigListData()
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+
+ return
+ }
+
+ valList, errMsg := xmlConfigData.FloatList("html/body/ul/li/a", "id")
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+ return
+ }
+ fmt.Println("TestFloat读取到的值:", valList)
+}
+
+// 字符串读取测试
+func TestStringList(t *testing.T) {
+ xmlConfigData, errMsg := getxmlConfigListData()
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+
+ return
+ }
+
+ valList, errMsg := xmlConfigData.StringList("html/body/ul/li/a", "id")
+ if errMsg != nil {
+ t.Error(errMsg)
+ t.Fail()
+ return
+ }
+ fmt.Println("TestString读取到的值:", valList)
+}
+
+func getxmlConfigListData() (xmlConfigData *XmlConfig, errMsg error) {
+ content := `
+
+
+ Hello
+
+
+
+ This is a H1
+
+
+ Hello,This is an example for gxpath.
+
+
+
+
+ `
+ var root *xmlUtil.Node
+ root, errMsg = xmlUtil.LoadFromString(content)
+ if errMsg == nil {
+ xmlConfigData = NewXmlConfig()
+ xmlConfigData.LoadFromXmlNode(root)
+ }
+
+ return
+}
diff --git a/.svn/pristine/48/48765b4ca5ea1ebef8ef05e1ac43f034ae2cc57a.svn-base b/.svn/pristine/48/48765b4ca5ea1ebef8ef05e1ac43f034ae2cc57a.svn-base
new file mode 100644
index 0000000..2233230
--- /dev/null
+++ b/.svn/pristine/48/48765b4ca5ea1ebef8ef05e1ac43f034ae2cc57a.svn-base
@@ -0,0 +1,4 @@
+/*
+数学助手包,提供一些与数学相关的助手方法
+*/
+package mathUtil
diff --git a/.svn/pristine/48/48c5b123aaa4f5248637d444f7ab2c0fef970cc8.svn-base b/.svn/pristine/48/48c5b123aaa4f5248637d444f7ab2c0fef970cc8.svn-base
new file mode 100644
index 0000000..f74b1ba
--- /dev/null
+++ b/.svn/pristine/48/48c5b123aaa4f5248637d444f7ab2c0fef970cc8.svn-base
@@ -0,0 +1,216 @@
+// 适用于大量http(s)请求,连接复用
+package webUtil
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptrace"
+ "net/url"
+ "time"
+)
+
+type Client struct {
+ traceCtx context.Context
+ client *http.Client
+}
+
+type TransportOPT struct {
+ //超时时间
+ Timeout time.Duration
+
+ //代理字符串,如"http://127.0.0.1:1080"
+ ProxyString string
+
+ //最大保持连接数
+ MaxIdleConns int
+
+ //每个主机的最大保持连接数
+ MaxIdleConnsPerHost int
+
+ //单主机最大连接数
+ MaxConnsPerHost int
+
+ //保持连接的超时时间
+ IdleConnTimeout time.Duration
+
+ //禁止保持连接
+ DisableKeepAlives bool
+}
+
+// GET请求
+func (c *Client) Get(urlStr string, header map[string]string) (result []byte, err error) {
+ req, err := http.NewRequestWithContext(c.traceCtx, http.MethodGet, urlStr, nil)
+ if err != nil {
+ //fmt.Println(err)
+ return
+ }
+
+ // 处理头部(包括默认头部,以及传入的头部集合)
+ if header == nil {
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ } else {
+ for k, v := range header {
+ req.Header.Add(k, v)
+ }
+ }
+
+ res, err := c.client.Do(req)
+ if err != nil {
+ //fmt.Println(err)
+ return
+ }
+ defer res.Body.Close()
+
+ result, err = ioutil.ReadAll(res.Body)
+
+ return
+}
+
+// POST请求
+func (c *Client) PostWithMap(urlStr string, data map[string]string, header map[string]string) (result []byte, err error) {
+ // 组装POST数据
+ postValues := url.Values{}
+ for key, value := range data {
+ postValues.Set(key, value)
+ }
+ postDataStr := postValues.Encode()
+ byteData := []byte(postDataStr)
+
+ var req *http.Request
+ req, err = http.NewRequestWithContext(c.traceCtx, http.MethodPost, urlStr, bytes.NewReader(byteData))
+ if err != nil {
+ //fmt.Println(err)
+ return
+ }
+
+ // 处理头部(包括默认头部,以及传入的头部集合)
+ if header == nil {
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ } else {
+ for k, v := range header {
+ req.Header.Add(k, v)
+ }
+ }
+
+ var res *http.Response
+ res, err = c.client.Do(req)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ defer res.Body.Close()
+
+ result, err = ioutil.ReadAll(res.Body)
+
+ return
+}
+
+// POST请求
+func (c *Client) PostWithByte(urlStr string, data []byte, header map[string]string) (result []byte, err error) {
+ var req *http.Request
+ req, err = http.NewRequestWithContext(c.traceCtx, http.MethodPost, urlStr, bytes.NewReader(data))
+ if err != nil {
+ //fmt.Println(err)
+ return
+ }
+
+ // 处理头部(包括默认头部,以及传入的头部集合)
+ if header == nil {
+ req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+ } else {
+ for k, v := range header {
+ req.Header.Add(k, v)
+ }
+ }
+
+ var res *http.Response
+ res, err = c.client.Do(req)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ defer res.Body.Close()
+
+ result, err = ioutil.ReadAll(res.Body)
+
+ return
+}
+
+// 新建Client对象
+// transportOPT参数说明
+//
+// Timeout - 连接绝对超时时间
+// ProxyString - 代理字符串
+// MaxIdleConns - 最大空闲连接数
+// MaxIdleConnsPerHost - 每个目标主机的最大空闲连接数
+// MaxConnsPerHost - 每个目标主机的最大连接数
+// IdleConnTimeout - 空闲连接超时时间
+// DisableKeepAlives - 禁用连接保持(要使用连接复用,此值不传入或传入false;否则连接可能不会复用)
+func NewClient(transportOPT *TransportOPT) (c *Client) {
+ c = &Client{}
+
+ //代理
+ getProxy := func() func(*http.Request) (*url.URL, error) {
+ if (transportOPT != nil) && len(transportOPT.ProxyString) > 0 {
+ uri, _ := url.Parse(transportOPT.ProxyString)
+ return http.ProxyURL(uri)
+ }
+
+ return nil
+ }
+
+ // 默认参数
+ timeout := 30 * time.Second
+ maxIdleConns := 60000
+ maxIdleConnsPerHost := 30000
+ maxConnsPerHost := 30000
+ idleConnTimeout := time.Minute * 1
+ disableKeepAlives := false
+
+ if transportOPT != nil {
+ // 根据传入参数修改默认参数
+ if transportOPT.Timeout > 0 {
+ timeout = transportOPT.Timeout
+ }
+ if transportOPT.MaxIdleConns > 0 {
+ maxIdleConns = transportOPT.MaxIdleConns
+ }
+ if transportOPT.MaxIdleConnsPerHost > 0 {
+ maxIdleConnsPerHost = transportOPT.MaxIdleConnsPerHost
+ }
+ if transportOPT.MaxConnsPerHost > 0 {
+ maxConnsPerHost = transportOPT.MaxConnsPerHost
+ }
+ if transportOPT.IdleConnTimeout > 0 {
+ idleConnTimeout = transportOPT.IdleConnTimeout
+ }
+
+ disableKeepAlives = transportOPT.DisableKeepAlives
+ }
+
+ clientTrace := &httptrace.ClientTrace{
+ //GotConn: func(gci httptrace.GotConnInfo) {
+ // fmt.Printf("conn was reused: %t\n", gci.Reused)
+ //},
+ }
+
+ c.traceCtx = httptrace.WithClientTrace(context.Background(), clientTrace)
+ c.client = &http.Client{
+ Timeout: timeout,
+
+ Transport: &http.Transport{
+ Proxy: getProxy(),
+ MaxIdleConns: maxIdleConns,
+ MaxIdleConnsPerHost: maxIdleConnsPerHost,
+ MaxConnsPerHost: maxConnsPerHost,
+ IdleConnTimeout: idleConnTimeout,
+ DisableKeepAlives: disableKeepAlives,
+ // ForceAttemptHTTP2: true,
+ },
+ }
+
+ return
+}
diff --git a/.svn/pristine/49/492bfe99e7af5f1f82645c1b1302f1536f95c33f.svn-base b/.svn/pristine/49/492bfe99e7af5f1f82645c1b1302f1536f95c33f.svn-base
new file mode 100644
index 0000000..0007c44
--- /dev/null
+++ b/.svn/pristine/49/492bfe99e7af5f1f82645c1b1302f1536f95c33f.svn-base
@@ -0,0 +1,225 @@
+package connection
+
+import (
+ "context"
+ "fmt"
+ "framework/sqlAsyncMgr"
+ goredis "github.com/go-redis/redis/v8"
+ "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "goutil/logUtilPlus"
+ "time"
+
+ // _ "github.com/go-sql-driver/mysql"
+ config "common/configsYaml"
+ "goutil/mysqlUtil"
+ "goutil/redisUtil"
+)
+
+var (
+ adminDB *gorm.DB //管理员数据库对象
+ userDB *gorm.DB //用户数据库对象
+ gameModelDB *gorm.DB // 游戏模型数据库对象
+ gameDB *gorm.DB // 游戏数据库
+ gamePlayerDB *gorm.DB // 玩家库
+ redisDB *goredis.Client // 游戏redis连接客户端
+ syncMgr *sqlAsyncMgr.SqlAsyncUtil // 同步管理对象
+ syncFileSize = 1024 * 1024 // 同步文件大小
+ fileMaxSaveTime = 24 * 7 // 保留7天的sql文件
+)
+
+var excuteSqlFunc func(*gorm.DB, ITable, string) error
+var loghandle func(s string, is ...interface{})
+var defaultType = SyncSql
+
+type ITable interface {
+ TableName() string
+}
+
+type SqlExecuteType int32
+
+const (
+ SyncSql SqlExecuteType = iota
+ ASyncSql
+ Name = "BaseDal"
+)
+
+// init
+// @description: init
+// parameter:
+// return:
+func init() {
+
+ //管理中心数据库配置
+ adminDB = initMysql(config.GetDbConfig().GetAdminConfig())
+ userDB = initMysql(config.GetDbConfig().GetUserConfig())
+
+ // 初始化游戏模型数据库
+ gameModelDBConfig := config.GetDbConfig().GetGameModelConfig()
+ gameModelDB = initMysql(gameModelDBConfig)
+
+ // 初始化crossSever 游戏数据库
+ gameDBConfig := config.GetDbConfig().GetGameConfig()
+ gameDB = initMysql(gameDBConfig)
+ gamePlayerDB = initMysql(config.GetDbConfig().GetPlayerConfig())
+
+ // 初始化redis-client
+ excuteSqlFunc = func(gdb *gorm.DB, table ITable, sql string) error {
+ db := gdb.Exec(sql)
+ if db.Error != nil {
+ loghandle("sql执行错误:%s;错误信息:%v", sql, db.Error.Error())
+ return db.Error
+ }
+
+ return nil
+ }
+
+ redisDB = initRedis(config.GetDbConfig().GetRedisConfig())
+}
+
+// 初始化Mysql
+// initMysql
+// @description: 初始化Mysql
+// parameter:
+// @dbConfig: dbConfig
+// return:
+// @*gorm.DB: DB
+func initMysql(dbConfig *mysqlUtil.DBConfig) *gorm.DB {
+
+ //不存在配置
+ if dbConfig == nil || dbConfig.ConnectionString == "" {
+ return nil
+ }
+ logUtilPlus.WarnLog("开始连接mysql:%s", dbConfig.ConnectionString)
+ dbObj, err := gorm.Open(mysql.Open(dbConfig.ConnectionString), &gorm.Config{})
+ if err != nil {
+ panic(fmt.Errorf("初始化数据库:%s失败,错误信息为:%s", dbConfig.ConnectionString, err))
+ }
+ logUtilPlus.WarnLog("连接mysql:%s成功", dbConfig.ConnectionString)
+
+ return dbObj
+}
+
+// initRedis
+// @description: 初始化redis客户端
+// parameter:
+// @redisConfig: redisConfig
+// return:
+// @*goredis.Client: Client
+func initRedis(redisConfig *redisUtil.RedisConfig) *goredis.Client {
+
+ client := goredis.NewClient(&goredis.Options{
+ Addr: redisConfig.ConnectionString,
+ Password: redisConfig.Password,
+ DB: redisConfig.Database,
+ IdleTimeout: redisConfig.IdleTimeout,
+ DialTimeout: redisConfig.DialConnectTimeout,
+ })
+
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ defer cancel()
+
+ ping, err := client.Ping(ctx).Result()
+ if err != nil {
+ panic(fmt.Errorf("ping->redis:%s失败,DB:%s,错误信息为:%s", redisConfig.ConnectionString, redisConfig.Database, err))
+ }
+
+ logUtilPlus.WarnLog("ping->redis:%s成功,信息为:%s", redisConfig.ConnectionString, ping)
+ return client
+}
+
+// GetAdminDB
+// @description: 获取admin库db实例
+// parameter:
+// return:
+// @*gorm.DB:admin库db实例
+func GetAdminDB() *gorm.DB {
+ return adminDB
+}
+
+// GetUserDB
+// @description: 获取user库db实例
+// parameter:
+// return:
+// @*gorm.DB:user库db实例
+func GetUserDB() *gorm.DB {
+ return userDB
+}
+
+// GetGameDB
+// @description: 获取game库db实例
+// parameter:
+// return:
+// @*gorm.DB:game库db实例
+func GetGameDB() *gorm.DB {
+ return gameDB
+}
+
+// GetPlayerDB
+// @description: 获取玩家库db实例
+// parameter:
+// return:
+// @*gorm.DB:玩家库db实例
+func GetPlayerDB() *gorm.DB {
+ return gamePlayerDB
+}
+
+// GetGameModelDB
+// @description: 获取model库db实例
+// parameter:
+// return:
+// @*gorm.DB:model库db实例
+func GetGameModelDB() *gorm.DB {
+ return gameModelDB
+}
+
+// GetRedisClient
+// @description: 获取redisdb实例
+// parameter:
+// return:
+// @*goredis.Client:redisdb实例
+func GetRedisClient() *goredis.Client {
+ return redisDB
+}
+
+// GetAll
+// @description: 获取model数据
+// parameter:
+// @dataList:数据列表
+// return:
+// @error:错误信息
+func GetAll(dataList interface{}) error {
+ mysqlObj := GetGameModelDB()
+ if mysqlObj = mysqlObj.Find(dataList); mysqlObj.Error != nil {
+ WriteLog("dal.GetAll", mysqlObj.Error)
+ return mysqlObj.Error
+ }
+
+ return nil
+}
+
+// GetGameModelData
+// @description: 获取GameModel数据
+// parameter:
+// @moduleName:模块名称
+// @dataList:数据列表
+// return:
+// @error:错误信息
+func GetGameModelData(moduleName string, dataList interface{}) error {
+ if result := gameModelDB.Find(dataList); result.Error != nil {
+ WriteLog(moduleName+"GetGameModelData", result.Error)
+ return result.Error
+ }
+
+ return nil
+}
+
+// WriteLog
+// @description: 记录错误日志
+// parameter:
+// @command:命令
+// @err:错误信息
+// return:
+func WriteLog(command string, err error) {
+ logUtilPlus.ErrorLog(fmt.Sprintf("Scan失败,错误信息:%s,command:%s", err, command))
+}
diff --git a/.svn/pristine/49/496a3674ea3bdc4d3c6456f7cd29c29cd7bd701d.svn-base b/.svn/pristine/49/496a3674ea3bdc4d3c6456f7cd29c29cd7bd701d.svn-base
new file mode 100644
index 0000000..7fb2dac
--- /dev/null
+++ b/.svn/pristine/49/496a3674ea3bdc4d3c6456f7cd29c29cd7bd701d.svn-base
@@ -0,0 +1,58 @@
+package model
+
+// 消费消息请求对象
+type GetQueueAttributesRequest struct {
+ // 公共请求参数
+ common *CommonRequest
+}
+
+// 获取请求方法名
+func (this *GetQueueAttributesRequest) GetActionName() string {
+ return "GetQueueAttributes"
+}
+
+// SetCommonRequestObject 设置公共请求对象
+func (this *GetQueueAttributesRequest) SetCommonRequest(commonRequest *CommonRequest) {
+ this.common = commonRequest
+}
+
+// AssembleParamMap 组装参数字典
+// 返回值
+// map[string]string:请求参数字典
+func (this *GetQueueAttributesRequest) AssembleParamMap() map[string]string {
+ paramMap := this.common.AssembleParamMap()
+
+ return paramMap
+}
+
+func NewGetQueueAttributesRequest() *GetQueueAttributesRequest {
+ return &GetQueueAttributesRequest{}
+}
+
+// 消费消息请求返回结果对象
+type GetQueueAttributesResponse struct {
+ *CommonResponse
+
+ MaxMsgHeapNum int `json:"maxMsgHeapNum"` // 最大堆积消息数。取值范围在公测期间为 1,000,000 - 10,000,000,正式上线后范围可达到 1000,000-1000,000,000。默认取值在公测期间为 10,000,000,正式上线后为 100,000,000。
+ PollingWaitSeconds int `json:"pollingWaitSeconds"` // 消息接收长轮询等待时间。取值范围0 - 30秒,默认值0。
+ VisibilityTimeout int `json:"visibilityTimeout"` // 消息可见性超时。取值范围1 - 43200秒(即12小时内),默认值30。
+ MaxMsgSize int `json:"maxMsgSize"` // 消息最大长度。取值范围1024 - 1048576 Byte(即1K - 1024K),默认值65536。
+ MsgRetentionSeconds int `json:"msgRetentionSeconds"` // 消息保留周期。取值范围60-1296000秒(1min-15天),默认值345600秒(4 天)。
+ CreateTime int `json:"createTime"` // 队列的创建时间。返回 Unix 时间戳,精确到秒。
+ LastModifyTime int `json:"lastModifyTime"` // 最后一次修改队列属性的时间。返回 Unix 时间戳,精确到秒。
+ ActiveMsgNum int `json:"activeMsgNum"` // 在队列中处于 Active 状态(不处于被消费状态)的消息总数,为近似值。
+ InactiveMsgNum int `json:"inactiveMsgNum"` // 在队列中处于 Inactive 状态(正处于被消费状态)的消息总数,为近似值。
+ RewindSeconds int `json:"rewindSeconds"` // 回溯队列的消息回溯时间最大值,取值范围0 - 43200秒,0表示不开启消息回溯。
+ RewindmsgNum int `json:"rewindmsgNum"` // 已调用 DelMsg 接口删除,但还在回溯保留时间内的消息数量。
+ MinMsgTime int `json:"minMsgTime"` // 消息最小未消费时间,单位为秒。
+ QueueName string `json:"queueName"` // 消息队列名字。
+ QueueId string `json:"queueId"` // 消息队列ID。
+ CreateUin int64 `json:"createUin"` // 创建者Uin。
+ Bps int `json:"Bps"` // 带宽限制。
+ Qps int `json:"qps"` // 每秒钟生产消息条数的限制,消费消息的大小是该值的1.1倍。
+ Tags []string `json:"tags"` // 关联的标签。
+}
+
+func NewGetQueueAttributesResponse() *GetQueueAttributesResponse {
+ return &GetQueueAttributesResponse{}
+}
diff --git a/.svn/pristine/49/4995fa2b02485de6eb3a2c938963067ee4ef19bf.svn-base b/.svn/pristine/49/4995fa2b02485de6eb3a2c938963067ee4ef19bf.svn-base
new file mode 100644
index 0000000..0160c32
--- /dev/null
+++ b/.svn/pristine/49/4995fa2b02485de6eb3a2c938963067ee4ef19bf.svn-base
@@ -0,0 +1,7 @@
+package httpSender
+
+// 发送器
+// 用于发送Requester
+type Sender interface {
+ Send(req Requester) ([]byte, error)
+}
diff --git a/.svn/pristine/49/49ee5106c29cff02591a87a5b23b6d636baf73e0.svn-base b/.svn/pristine/49/49ee5106c29cff02591a87a5b23b6d636baf73e0.svn-base
new file mode 100644
index 0000000..ec7d8cd
--- /dev/null
+++ b/.svn/pristine/49/49ee5106c29cff02591a87a5b23b6d636baf73e0.svn-base
@@ -0,0 +1,126 @@
+package contextcheckMgr
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/rand"
+ "sort"
+ "strconv"
+ "time"
+
+ "goutil/logUtil"
+ "goutil/securityUtil"
+ "goutil/webUtil"
+)
+
+var (
+ //接口密钥Id
+ msecretId string = "c98276c73c122eaa65163fe431cbf7d4"
+ //接口密钥key
+ msecretKey string = "3d2b39f824fa2f992494e17be500e303"
+ //业务ID
+ mbusinessId string = "9559ce74b5c5d24f6b124799a53c7431"
+ //接口请求地址
+ mapiurl string = "http://as.dun.163.com/v3/text/check"
+ //版本号
+ mversion string = "v3.1"
+)
+
+//参数设置
+func SetPara(secretId, secretKey, businessId, apiurl, version string) {
+ msecretId = secretId
+ msecretKey = secretKey
+ mbusinessId = businessId
+ mapiurl = apiurl
+ mversion = version
+}
+
+//content:用户发表内容
+//account:玩家账号(用户唯一标识)
+//nickname:角色名称
+//extStr1:角色区服名称
+//extStr2:UserId
+//ip:用户IP地址,建议抄送,辅助机审策略精准调优
+//extLon1:区服ID
+//返回值 code: 0:通过, 1:嫌疑,2:不通过
+//文本内容检测
+func TextCheck(content, account, nickname, extStr1, extStr2, ip string, extLon1 int64) (code int, err error) {
+ //构造请求参数
+ postDataDict := make(map[string]string)
+ postDataDict["secretId"] = msecretId
+ postDataDict["businessId"] = mbusinessId
+ postDataDict["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
+ postDataDict["nonce"] = strconv.FormatInt(rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(10000000000), 10)
+ rawString := fmt.Sprintf("%v%v%v", account, postDataDict["timestamp"], content)
+ postDataDict["dataId"] = securityUtil.Md5String(rawString, false)
+ postDataDict["content"] = content
+ postDataDict["version"] = mversion
+ postDataDict["account"] = account
+ postDataDict["nickname"] = nickname
+ postDataDict["extLon1"] = strconv.FormatInt(extLon1, 10)
+ // postDataDict["extLon2"] = extLon2
+ postDataDict["extStr1"] = extStr1
+ postDataDict["extStr2"] = extStr2
+ postDataDict["ip"] = ip
+ postDataDict["signature"] = getSignature(postDataDict)
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ //请求接口
+ statusCode, result, err := webUtil.PostMapData(mapiurl, postDataDict, header, transport)
+ //定义错误信息
+ var logMessage string
+
+ //post请求错误
+ if err != nil {
+ logMessage = fmt.Sprintf("TextCheck:,错误信息为:%s", err.Error())
+ logUtil.ErrorLog(logMessage)
+ return
+ }
+ if statusCode != 200 {
+ logMessage = fmt.Sprintf("TextCheck:%d is wrong", statusCode)
+ logUtil.ErrorLog(logMessage)
+ err = fmt.Errorf("TextCheck:%d is wrong", statusCode)
+ return
+ }
+
+ //反序列化结果
+ var checkResponseObj *ResultModel
+ err = json.Unmarshal(result, &checkResponseObj)
+ if err != nil {
+ logMessage = fmt.Sprintf("json.Unmarshal(checkResponseObj),err:%s", err.Error())
+ logUtil.ErrorLog(logMessage)
+ return
+ }
+
+ //判断接口是否调用成功
+ if checkResponseObj.Code != 200 {
+ logMessage = fmt.Sprintf("TextCheck接口调用失败,ResultStatus %d", checkResponseObj.Code)
+ err = fmt.Errorf("TextCheck接口调用失败,code:%d", checkResponseObj.Code)
+ return
+ }
+
+ //返回检测结果
+ code = checkResponseObj.Result.Action
+ return
+}
+
+//生成签名字符串
+func getSignature(postDataDict map[string]string) string {
+ var paramStr string
+ keys := make([]string, 0, len(postDataDict))
+ for k := range postDataDict {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, key := range keys {
+ paramStr += key + postDataDict[key]
+ }
+ paramStr += msecretKey
+
+ return securityUtil.Md5String(paramStr, false)
+}
diff --git a/.svn/pristine/4a/4a49ef451d4b9f74fdb2c8830143bbaec17f3ce3.svn-base b/.svn/pristine/4a/4a49ef451d4b9f74fdb2c8830143bbaec17f3ce3.svn-base
new file mode 100644
index 0000000..b96f89c
--- /dev/null
+++ b/.svn/pristine/4a/4a49ef451d4b9f74fdb2c8830143bbaec17f3ce3.svn-base
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/.svn/pristine/4b/4b8e1ac3d261e7448019224293b8c2f300ee0ab3.svn-base b/.svn/pristine/4b/4b8e1ac3d261e7448019224293b8c2f300ee0ab3.svn-base
new file mode 100644
index 0000000..efc382b
--- /dev/null
+++ b/.svn/pristine/4b/4b8e1ac3d261e7448019224293b8c2f300ee0ab3.svn-base
@@ -0,0 +1,27 @@
+package zooKeeperMgr
+
+import (
+ "testing"
+ "time"
+
+ "github.com/samuel/go-zookeeper/zk"
+)
+
+func TestCascadeCreate(t *testing.T) {
+ zkConfigObj := &ZooKeeperConfig {
+ Servers: "172.27.0.4:2181,172.27.0.6:2181,172.27.0.9:2181",
+ StartPath: "/Develop/GameServer",
+ SessionTimeout: 10 * time.Second,
+ }
+
+ conn, _, err := zk.Connect(zkConfigObj.GetServerList(), zkConfigObj.SessionTimeout)
+ if err != nil {
+ panic(err)
+ }
+ defer conn.Close()
+
+ err = CascadeCreate(conn, zkConfigObj.StartPath)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is:%v", err)
+ }
+}
\ No newline at end of file
diff --git a/.svn/pristine/4c/4c23f994a6d4b535e3554239a36e580922efb062.svn-base b/.svn/pristine/4c/4c23f994a6d4b535e3554239a36e580922efb062.svn-base
new file mode 100644
index 0000000..1030862
--- /dev/null
+++ b/.svn/pristine/4c/4c23f994a6d4b535e3554239a36e580922efb062.svn-base
@@ -0,0 +1,77 @@
+package sqlAsyncMgr
+
+import (
+ "sync"
+ "sync/atomic"
+)
+
+// SqlAsyncIdentityStatistics sql标识统计类
+type SqlAsyncIdentityStatistics struct {
+ // 锁对象
+ m sync.Mutex
+
+ // 当前正在同步的sql数量
+ syncCount int32
+
+ // 待同步的统计
+ statisticData map[string]*StatisticModel
+}
+
+// newSqlAsyncIdentityStatistics 创建新StatisticModel对象
+func newSqlAsyncIdentityStatistics() *SqlAsyncIdentityStatistics {
+ return &SqlAsyncIdentityStatistics{
+ statisticData: make(map[string]*StatisticModel),
+ }
+}
+
+// getItem 获取指定统计对象
+func (this *SqlAsyncIdentityStatistics) getItem(_identityId string, isCreate bool) *StatisticModel {
+ this.m.Lock()
+ defer this.m.Unlock()
+
+ if item, exists := this.statisticData[_identityId]; exists {
+ return item
+ }
+
+ if isCreate == false {
+ return nil
+ }
+
+ newItem := newStatisticModel(_identityId)
+ this.statisticData[_identityId] = newItem
+
+ return newItem
+}
+
+// AddCount 指定标识添加数量
+func (this *SqlAsyncIdentityStatistics) AddCount(_identityId string, count int32) {
+ model := this.getItem(_identityId, true)
+ model.AddCount(count)
+
+ // 原子操作相加
+ atomic.AddInt32(&this.syncCount, count)
+}
+
+// Reduce 指定标识减少数量
+func (this *SqlAsyncIdentityStatistics) Reduce(_identityId string, count int32) {
+ if model := this.getItem(_identityId, false); model != nil {
+ model.ReduceCount(count)
+ }
+
+ // 原子操作相减
+ atomic.AddInt32(&this.syncCount, -count)
+}
+
+// GetCount 获取指定标识的数量
+func (this *SqlAsyncIdentityStatistics) GetCount(_identityId string) int32 {
+ if model := this.getItem(_identityId, false); model != nil {
+ return model.Count
+ }
+
+ return 0
+}
+
+// GetAllCount 获取总的待写入数据
+func (this *SqlAsyncIdentityStatistics) GetAllCount() int32 {
+ return this.syncCount
+}
diff --git a/.svn/pristine/4c/4cdf5c756ca8b6b4c1684486b413f058cbcdef5b.svn-base b/.svn/pristine/4c/4cdf5c756ca8b6b4c1684486b413f058cbcdef5b.svn-base
new file mode 100644
index 0000000..4f400e2
--- /dev/null
+++ b/.svn/pristine/4c/4cdf5c756ca8b6b4c1684486b413f058cbcdef5b.svn-base
@@ -0,0 +1,18 @@
+package managecenterModel
+
+// 服务器组热度
+type GroupHeat int32
+
+const (
+ // 正常
+ Con_GroupHeat_Normal GroupHeat = 1
+
+ // 新服
+ Con_GroupHeat_New GroupHeat = 2
+
+ // 推荐
+ Con_GroupHeat_Recommend GroupHeat = 3
+
+ // 热门
+ Con_GroupHeat_Heat GroupHeat = 4
+)
diff --git a/.svn/pristine/4d/4d9ed17b45d8fe9611097a5640452068f52cfc06.svn-base b/.svn/pristine/4d/4d9ed17b45d8fe9611097a5640452068f52cfc06.svn-base
new file mode 100644
index 0000000..fa17bbf
--- /dev/null
+++ b/.svn/pristine/4d/4d9ed17b45d8fe9611097a5640452068f52cfc06.svn-base
@@ -0,0 +1,208 @@
+package bytesSendUtil
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+ "sync"
+ "time"
+
+ "goutil/intAndBytesUtil"
+ "goutil/logUtil"
+)
+
+var (
+ errConnectEmpty = fmt.Errorf("scoket reconnecting...")
+ byterOrder = binary.LittleEndian
+)
+
+// 实现 EnsureSender和sender接口
+type tcpSender struct {
+ // 需要实现的接口
+ EnsureSender
+
+ // 包含sender接口部分实现
+ *baseSender
+
+ // 数据目录
+ dataFolder string
+
+ // 服务器地址
+ address string
+
+ // 连接
+ conn net.Conn
+
+ // 用于重连时互斥
+ mutex sync.Mutex
+
+ // 用于sendLoop和resendLoop发送退出信号
+ closeSignal chan struct{}
+}
+
+// 创建一个tcp数据发送器
+// 参数:
+//
+// _dataFolder 数据存放目录
+// _address 连接地址
+func NewTCPSender(_dataFolder, _address string) (EnsureSender, error) {
+ // 连接服务器
+ conn, err := net.DialTimeout("tcp", _address, 5*time.Second)
+ if err != nil {
+ return nil, err
+ }
+
+ this := &tcpSender{
+ dataFolder: _dataFolder,
+ baseSender: newBaseSender(),
+ address: _address,
+ conn: conn,
+ closeSignal: make(chan struct{}),
+ }
+
+ // 新开协程发送数据
+ go sendLoop(this, this.closeSignal)
+
+ // 定时重发
+ go resendLoop(this, _dataFolder, this.closeSignal)
+
+ // 发送心跳包
+ go this.heartBeat()
+
+ return this, nil
+}
+
+// 每隔15秒发送心跳包
+func (this *tcpSender) heartBeat() {
+ defer func() {
+ if r := recover(); r != nil {
+ logUtil.LogUnknownError(r)
+ }
+ }()
+
+ tick := time.Tick(time.Second * 15)
+
+ for {
+ select {
+ case <-this.Done():
+ return
+ case <-tick:
+ this.sendBytes([]byte{})
+ }
+ }
+}
+
+// EnsureSender接口
+// Write:写入数据
+func (this *tcpSender) Write(data []byte) error {
+ item, err := newTCPDataItem(data)
+ if err != nil {
+ return err
+ }
+
+ this.waitingDataChan <- item
+
+ return nil
+}
+
+// EnsureSender接口
+// Close:关闭
+func (this *tcpSender) Close() error {
+ close(this.done)
+
+ // 关闭socket连接
+ conn := this.conn
+ if conn != nil {
+ conn.Close()
+ }
+
+ // 等待sendLoop和resendLoop退出
+ <-this.closeSignal
+ <-this.closeSignal
+
+ // 保存数据
+ _, e1 := saveData(this.Cache(), this.dataFolder)
+ _, e2 := saveData(this.Data(), this.dataFolder)
+
+ if e2 != nil {
+ if e1 != nil {
+ return fmt.Errorf("%s %s", e1, e2)
+ }
+ return e2
+ } else {
+ return e1
+ }
+}
+
+// Sender接口
+// Send:发送dataItem
+func (this *tcpSender) Send(item dataItem) error {
+ err := this.sendBytes(item.Bytes())
+ if err != nil && err != errConnectEmpty {
+ // 发送失败时发送次数+1
+ item.SetCount(item.Count() + 1)
+ }
+
+ return err
+}
+
+// 发送字节数据
+// 发送格式:[lenght+data]
+func (this *tcpSender) sendBytes(data []byte) error {
+ conn := this.conn
+ if conn == nil {
+ return errConnectEmpty
+ }
+
+ // 将长度转化为字节数组
+ header := intAndBytesUtil.Int32ToBytes(int32(len(data)), byterOrder)
+
+ if len(data) > 0 {
+ data = append(header, data...)
+ } else {
+ data = header
+ }
+
+ _, err := conn.Write(data)
+ if err != nil {
+ this.mutex.Lock()
+ // 发送失败
+ // 检查失败的conn是否this.conn(避免多个线程失败后均调用reconnect)
+ // 是则关闭并重连
+ if conn == this.conn {
+ this.conn.Close()
+ this.conn = nil
+ this.mutex.Unlock()
+
+ // 重连
+ go this.reconnect()
+ } else {
+ this.mutex.Unlock()
+ }
+ }
+
+ return err
+}
+
+// 重连服务器
+func (this *tcpSender) reconnect() error {
+ // lock-it
+ this.mutex.Lock()
+ defer this.mutex.Unlock()
+
+ for {
+ // 检查是否已经重连
+ if this.conn != nil {
+ return nil
+ }
+
+ conn, err := net.DialTimeout("tcp", this.address, 5*time.Second)
+ if err != nil {
+ // 连接失败,5秒后重试
+ <-time.After(time.Second * 5)
+ continue
+ }
+
+ this.conn = conn
+ }
+}
diff --git a/.svn/pristine/4d/4de7d0e1719fe7c5227e762a9cfdbfea79af5c81.svn-base b/.svn/pristine/4d/4de7d0e1719fe7c5227e762a9cfdbfea79af5c81.svn-base
new file mode 100644
index 0000000..2242ca7
--- /dev/null
+++ b/.svn/pristine/4d/4de7d0e1719fe7c5227e762a9cfdbfea79af5c81.svn-base
@@ -0,0 +1,37 @@
+version: '3'
+services:
+ mysql:
+ image: mysql:8.0
+ container_name: mysql-admin
+ environment:
+ MYSQL_ROOT_PASSWORD: 123456
+ MYSQL_DATABASE: admin,user
+ volumes:
+ - /my/own/datadir:/var/lib/mysql
+ ports:
+ - "3306:3306"
+ redis:
+ image: redis:7.0
+ container_name: redis-admin
+ ports:
+ - "6379:6379"
+ volumes:
+ - redis_data:/data
+ restart: always
+ command: ["redis-server", "--appendonly", "yes"]
+
+ admin-center:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: admin-center
+ ports:
+ - "10051:10051"
+ volumes:
+ - ./app:/app
+ depends_on:
+ - mysql
+ - redis
+
+volumes:
+ redis_data:
\ No newline at end of file
diff --git a/.svn/pristine/4e/4e0d2175915e4e0a382656f419b23ec37c1dea9a.svn-base b/.svn/pristine/4e/4e0d2175915e4e0a382656f419b23ec37c1dea9a.svn-base
new file mode 100644
index 0000000..8f3ebec
--- /dev/null
+++ b/.svn/pristine/4e/4e0d2175915e4e0a382656f419b23ec37c1dea9a.svn-base
@@ -0,0 +1,77 @@
+// Package routineCtrlUtil
+//
+// @description: 协程控制-用于海量循环中,限制并发的最大同时执行协程数
+// @author:
+// @revision history:
+// @create date: 2022-02-23 17:23:06
+package routineCtrlUtil
+
+import "sync"
+
+// RoutineCtrl
+//
+// @description: 控制同时运行的协程数
+type RoutineCtrl struct {
+ wg *sync.WaitGroup
+ chNum chan struct{}
+}
+
+// Run
+//
+// @description: 循环内待执行的协程,封装在f函数参数内执行。f函数的最大并发运行数受New参数maxNum限制
+// 注意:*** 待执行函数引用外变变量,程序可能会出现不符合逻辑的结果(外部变量变化时,闭包函数获取到的是变化后的变量值) ***
+// *** 闭包函数避坑说明 ***
+// 方式1)将待执行函数内使用的外部变量,用参数传入,可避免不符合逻辑的结果
+// 方式2)将待执行函数内使用的外部变量,使用一个临时局部变量将其值“固定”下来,闭包内使用临时局部变量(临时局部变量不会再被修改)
+// 示例:routine_ctrl_test.go -> TestRoutineCtrl
+//
+// parameter:
+//
+// @receiver rtCtrl:
+// @f: 循环内待执行的协程
+//
+// return:
+func (rtCtrl *RoutineCtrl) Run(f func(interface{}), arg interface{}) {
+ rtCtrl.wg.Add(1)
+ rtCtrl.chNum <- struct{}{}
+ go func() {
+ defer func() {
+ <-rtCtrl.chNum
+ rtCtrl.wg.Done()
+ recover() // 异常捕获
+ }()
+
+ f(arg) // 调用实际函数体
+ }()
+}
+
+// Wait
+//
+// @description: 在循环外面等待所有协程执行结束后返回
+//
+// parameter:
+//
+// @receiver rtCtrl:
+//
+// return:
+func (rtCtrl *RoutineCtrl) Wait() {
+ rtCtrl.wg.Wait()
+}
+
+// New
+//
+// @description: 产生一个协程控制对象
+//
+// parameter:
+//
+// @maxNum: 限制调用Run时的f函数的最大运行协程数
+//
+// return:
+//
+// @*RoutineCtrl:
+func New(maxNum int) *RoutineCtrl {
+ return &RoutineCtrl{
+ wg: &sync.WaitGroup{},
+ chNum: make(chan struct{}, maxNum),
+ }
+}
diff --git a/.svn/pristine/51/5134bf90a024b2d740a38545632f8b07a313f9ec.svn-base b/.svn/pristine/51/5134bf90a024b2d740a38545632f8b07a313f9ec.svn-base
new file mode 100644
index 0000000..1cd3267
--- /dev/null
+++ b/.svn/pristine/51/5134bf90a024b2d740a38545632f8b07a313f9ec.svn-base
@@ -0,0 +1,182 @@
+package webUtil
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strings"
+)
+
+// GET数据
+// weburl:远程服务器地址
+// header:包头集合
+// 返回值:
+// 返回的字节
+// 错误对象
+func GetWebData(weburl string, header map[string]string) (result []byte, err error) {
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("GET", weburl, nil)
+ if err != nil {
+ return
+ }
+
+ // 处理包头
+ if header != nil {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ transport := NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 读取数据
+ if response.StatusCode == http.StatusOK {
+ result, err = ioutil.ReadAll(response.Body)
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+// GET数据(新方法)
+// weburl:远程服务器地址
+// data:数据集合
+// header:包头内容
+// transport:transport对象
+// 返回值
+// http StatusCode
+// 字节数组
+// 错误对象
+func GetWebData2(weburl string, data map[string]string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
+ // 处理data,将data以key=value的形式拼接到weburl后,形成一个完整的url
+ dataStr := ""
+ count := 0
+ for k, v := range data {
+ if count == len(data)-1 {
+ dataStr += fmt.Sprintf("%s=%s", k, v)
+ } else {
+ dataStr += fmt.Sprintf("%s=%s&", k, v)
+ }
+ count += 1
+ }
+
+ if dataStr != "" {
+ if strings.Contains(weburl, "?") {
+ weburl = fmt.Sprintf("%s&%s", weburl, dataStr)
+ } else {
+ weburl = fmt.Sprintf("%s?%s", weburl, dataStr)
+ }
+ }
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("GET", weburl, nil)
+ if err != nil {
+ return
+ }
+
+ // 处理头部
+ if header != nil {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ if transport == nil {
+ transport = NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+ }
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 获取返回值
+ statusCode = response.StatusCode
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
+
+// GET数据(新方法)
+// weburl:远程服务器地址
+// dataStr:参数字符串
+// header:包头内容
+// transport:transport对象
+// 返回值
+// http StatusCode
+// 字节数组
+// 错误对象
+func GetWebData3(weburl string, dataStr string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
+ if dataStr != "" {
+ if strings.Contains(weburl, "?") {
+ weburl = fmt.Sprintf("%s&%s", weburl, dataStr)
+ } else {
+ weburl = fmt.Sprintf("%s?%s", weburl, dataStr)
+ }
+ }
+
+ // 构造请求对象
+ var request *http.Request
+ request, err = http.NewRequest("GET", weburl, nil)
+ if err != nil {
+ return
+ }
+
+ // 处理头部
+ if header != nil {
+ for k, v := range header {
+ request.Header.Add(k, v)
+ }
+ }
+
+ // 构造transport对象
+ if transport == nil {
+ transport = NewTransport()
+ transport.DisableKeepAlives = true
+ transport = GetTimeoutTransport(transport, 30)
+ }
+
+ // 构造httpClient对象
+ client := &http.Client{Transport: transport}
+
+ // 发送数据
+ var response *http.Response
+ response, err = client.Do(request)
+ if err != nil {
+ return
+ }
+ defer response.Body.Close()
+
+ // 获取返回值
+ statusCode = response.StatusCode
+ result, err = ioutil.ReadAll(response.Body)
+
+ return
+}
diff --git a/.svn/pristine/51/51904f3f8b846194d5b8e73a078da71adaae6dfd.svn-base b/.svn/pristine/51/51904f3f8b846194d5b8e73a078da71adaae6dfd.svn-base
new file mode 100644
index 0000000..c9bfdad
--- /dev/null
+++ b/.svn/pristine/51/51904f3f8b846194d5b8e73a078da71adaae6dfd.svn-base
@@ -0,0 +1,4 @@
+/*
+用于提供验证AppStore充值的逻辑
+*/
+package appChargeUtil
diff --git a/.svn/pristine/51/51e48b01a62c7b4795266420a89faf8955b3a29c.svn-base b/.svn/pristine/51/51e48b01a62c7b4795266420a89faf8955b3a29c.svn-base
new file mode 100644
index 0000000..d2f0e91
--- /dev/null
+++ b/.svn/pristine/51/51e48b01a62c7b4795266420a89faf8955b3a29c.svn-base
@@ -0,0 +1,13 @@
+package managecenterModel
+
+// MC系统配置列表对象
+type SysConfig struct {
+ // 新服有效天数
+ NewServerValidDays int32 `json:"NewServerValidDays"`
+
+ // 用户Id
+ WhiteListServerIds string `json:"WhiteListServerIds"`
+
+ //登录本地验证key
+ DynamicLoginKey string `json:"DynamicLoginKey"`
+}
diff --git a/.svn/pristine/52/52095a281285493617e456ee5193122cba2fe3e3.svn-base b/.svn/pristine/52/52095a281285493617e456ee5193122cba2fe3e3.svn-base
new file mode 100644
index 0000000..c1e47c4
--- /dev/null
+++ b/.svn/pristine/52/52095a281285493617e456ee5193122cba2fe3e3.svn-base
@@ -0,0 +1,186 @@
+package mathUtil
+
+import (
+ "sort"
+)
+
+// 判断传入的byte型数组是否连续
+func IsContinuous_byte(list []byte) bool {
+ if len(list) == 0 || len(list) == 1 {
+ return true
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsContinuous_int64(list_int64)
+}
+
+// 判断传入的int型数组是否连续
+func IsContinuous_int(list []int) bool {
+ if len(list) == 0 || len(list) == 1 {
+ return true
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsContinuous_int64(list_int64)
+}
+
+// 判断传入的int型数组是否连续
+func IsContinuous_int32(list []int32) bool {
+ if len(list) == 0 || len(list) == 1 {
+ return true
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsContinuous_int64(list_int64)
+}
+
+// 判断传入的int型数组是否连续
+func IsContinuous_int64(list []int64) bool {
+ if len(list) == 0 || len(list) == 1 {
+ return true
+ }
+
+ if int64(len(list)) != list[len(list)-1]-list[0]+1 {
+ return false
+ }
+
+ for i := 0; i < len(list)-1; i++ {
+ if list[i]+1 != list[i+1] {
+ return false
+ }
+ }
+
+ return true
+}
+
+// 判断区间是否连续
+func IsContinuous_Region(list []*IntRegion) bool {
+ if len(list) == 0 || len(list) == 1 {
+ return true
+ }
+
+ sort.Slice(list, func(i, j int) bool { return list[i].Lower < list[j].Lower })
+
+ for i := 0; i < len(list)-1; i++ {
+ if list[i].IsSorted() == false || list[i+1].IsSorted() == false {
+ return false
+ }
+
+ if list[i].Upper+1 != list[i+1].Lower {
+ return false
+ }
+ }
+
+ return true
+}
+
+// 判断传入的概率是否全覆盖
+func IsOddFullConvered(list []*IntRegion, min, max int) bool {
+ if len(list) == 0 {
+ return false
+ }
+
+ if list[0].Lower != min || list[len(list)-1].Upper != max {
+ return false
+ }
+
+ sort.Slice(list, func(i, j int) bool { return list[i].Lower < list[j].Lower })
+
+ for i := 0; i < len(list)-1; i++ {
+ if list[i].IsSorted() == false || list[i+1].IsSorted() == false {
+ return false
+ }
+
+ if list[i].Upper+1 != list[i+1].Lower {
+ return false
+ }
+ }
+
+ return true
+}
+
+func IsDistinct_byte(list []byte) (result bool) {
+ if len(list) == 0 || len(list) == 1 {
+ result = true
+ return
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsDistinct_int64(list_int64)
+}
+
+func IsDistinct_int(list []int) (result bool) {
+ if len(list) == 0 || len(list) == 1 {
+ result = true
+ return
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsDistinct_int64(list_int64)
+}
+
+func IsDistinct_int32(list []int32) (result bool) {
+ if len(list) == 0 || len(list) == 1 {
+ result = true
+ return
+ }
+
+ list_int64 := make([]int64, len(list), len(list))
+ for i, v := range list {
+ list_int64[i] = int64(v)
+ }
+
+ return IsDistinct_int64(list_int64)
+}
+
+// 判断int64数组是否内容唯一
+func IsDistinct_int64(list []int64) (result bool) {
+ if len(list) == 0 || len(list) == 1 {
+ result = true
+ return
+ }
+
+ sort.Slice(list, func(i, j int) bool { return list[i] < list[j] })
+
+ for i := 0; i < len(list)-1; i++ {
+ if list[i] == list[i+1] {
+ result = false
+ return
+ }
+ }
+
+ result = true
+ return
+}
+
+//// 将int转成uint类型(因goutil指定go版本过低,不支持泛型,未实际加入;要使用的人取消注释,并指定允许泛型的go版本)
+//// 应用场景:atomic.AddUint64 想减1时
+////
+//// x := uint64(1000)
+//// y := int64(-1)
+//// atomic.AddUint64(&x, intToUint[int64, uint64](y))
+//func intToUint[T1 int8 | int16 | int32 | int64 | int, T2 uint8 | uint16 | uint32 | uint64 | uint](x T1) T2 {
+// // 写到函数内,两种方式都可以;若直接使用,只能使用^T2(-x - 1);若使用T2(x)方式,x为负值时转为uint类语法检查无法通过
+// return ^T2(-x - 1)
+// // return T2(x)
+//}
diff --git a/.svn/pristine/52/521f814a989f3a71d3af9af1cc1514017f4c3b2d.svn-base b/.svn/pristine/52/521f814a989f3a71d3af9af1cc1514017f4c3b2d.svn-base
new file mode 100644
index 0000000..1c5773c
--- /dev/null
+++ b/.svn/pristine/52/521f814a989f3a71d3af9af1cc1514017f4c3b2d.svn-base
@@ -0,0 +1,53 @@
+package stringUtil
+
+import (
+ "testing"
+)
+
+func TestBase64Encode(t *testing.T) {
+ greeting := "Hello world"
+ encoded := Base64Encode(greeting)
+ decoded, err := Base64Decode(encoded)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is one:%s", err)
+ return
+ }
+
+ if greeting != decoded {
+ t.Errorf("Expected %s, but got %s", greeting, decoded)
+ return
+ }
+}
+
+func TestBase64Encode2(t *testing.T) {
+ greeting := []byte("Hello world")
+ encoded := Base64Encode2(greeting)
+ decoded, err := Base64Decode2(encoded)
+ if err != nil {
+ t.Errorf("There should be no error, but now there is one:%s", err)
+ return
+ }
+
+ if isEqual(greeting, decoded) == false {
+ t.Errorf("Expected %s, but got %s", greeting, decoded)
+ return
+ }
+}
+
+func isEqual(s1, s2 []byte) bool {
+ if s1 == nil || s2 == nil {
+ return true
+ }
+
+ if len(s1) != len(s2) {
+ return false
+ }
+
+ for i := 0; i < len(s1); i++ {
+ if s1[i] != s2[i] {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/.svn/pristine/52/5237995ae7afcad71966e2a8f30ed0f0ee23991f.svn-base b/.svn/pristine/52/5237995ae7afcad71966e2a8f30ed0f0ee23991f.svn-base
new file mode 100644
index 0000000..41cbcc5
--- /dev/null
+++ b/.svn/pristine/52/5237995ae7afcad71966e2a8f30ed0f0ee23991f.svn-base
@@ -0,0 +1,14 @@
+package impl_console
+
+import (
+ "testing"
+)
+
+func TestInfoLog(t *testing.T) {
+ log := NewLogger()
+ log.DebugLog("Debug test")
+ log.InfoLog("Info test")
+ log.WarnLog("Warn test")
+ log.ErrorLog("Error test")
+ log.FatalLog("Fatal test")
+}
diff --git a/.svn/pristine/52/526ed4f4997979f5889d26f7a025ec34dd3405f1.svn-base b/.svn/pristine/52/526ed4f4997979f5889d26f7a025ec34dd3405f1.svn-base
new file mode 100644
index 0000000..6eb647c
--- /dev/null
+++ b/.svn/pristine/52/526ed4f4997979f5889d26f7a025ec34dd3405f1.svn-base
@@ -0,0 +1,132 @@
+package managecenterMgr
+
+import (
+ "fmt"
+ "testing"
+)
+
+func init() {
+ manageCenterDataSwitchObj := &ManageCenterDataSwitch{
+ AllDataSwitch: true,
+ }
+ Start("https://managecenterapi-sd3.7qule.com/", manageCenterDataSwitchObj)
+
+ item, exist := GetAreaLabelDBByGroupId(82)
+ if exist {
+ fmt.Printf("%v", item)
+ }
+}
+
+func TestPartner(t *testing.T) {
+ partnerList := GetPartnerList()
+ fmt.Printf("PartnerList count:%v\n", len(partnerList))
+ if len(partnerList) == 0 {
+ t.Errorf("There is no partner.")
+ return
+ }
+
+ firstPartner := partnerList[0]
+ _, exist := GetPartner(firstPartner.Id)
+ if !exist {
+ t.Errorf("Partner with Id:%d should exist, but now it doesn't.", firstPartner.Id)
+ return
+ }
+
+ _, exist = GetPartnerByAlias(firstPartner.Alias)
+ if !exist {
+ t.Errorf("Partner with Alias:%s should exist, but now it doesn't.", firstPartner.Alias)
+ return
+ }
+
+ _, exist, err := GetOtherConfigInfo(firstPartner.Id, "LoginHandler")
+ if err != nil {
+ t.Errorf("There should no error for Partner:%d, but now there is one:%v", err, firstPartner.Id)
+ return
+ }
+ if !exist {
+ t.Errorf("Partner with Id:%d should have an other config named LoginHandler, but now there isn't.", firstPartner.Id)
+ return
+ }
+}
+
+func TestServer(t *testing.T) {
+ serverGroupList := GetServerGroupList()
+ if len(serverGroupList) == 0 {
+ t.Errorf("There is no ServerGroup.")
+ return
+ }
+ firstServerGroup := serverGroupList[0]
+
+ serverList := GetServerListByGroupId(firstServerGroup.Id)
+ fmt.Printf("There are %d servers of GroupId:%d\n", len(serverList), firstServerGroup.Id)
+
+ firstServer := serverList[0]
+ serverList = GetServerListByPartnerId(firstServer.PartnerId)
+ fmt.Printf("There are %d servers of PartnerId:%d\n", len(serverList), firstServer.PartnerId)
+
+ _, exist := GetServerItem(firstServer.PartnerId, firstServer.Id)
+ if !exist {
+ t.Errorf("There is no server with PartnerId:%d, ServerId:%d.", firstServer.PartnerId, firstServer.Id)
+ return
+ }
+
+ distinctServerIdList := GetDistinctServerIdList()
+ fmt.Printf("There are %d distinct ServerId\n", len(distinctServerIdList))
+}
+
+func TestServerGroup(t *testing.T) {
+ serverGroupList := GetServerGroupList()
+ if len(serverGroupList) == 0 {
+ t.Errorf("There is no ServerGroup.")
+ return
+ }
+
+ firstServerGroup := serverGroupList[0]
+ _, exist := GetServerGroupItem(firstServerGroup.Id)
+ if !exist {
+ t.Errorf("The ServerGroup with Id:%d should exist, but now it doesn't.", firstServerGroup.Id)
+ return
+ }
+
+ serverList := GetServerListByGroupId(firstServerGroup.Id)
+ if len(serverList) == 0 {
+ t.Errorf("There is no server of ServerGroupId:%d", firstServerGroup.Id)
+ return
+ }
+ firstServer := serverList[0]
+ _, _, exist = GetServerGroup(firstServer.PartnerId, firstServer.Id)
+ if !exist {
+ t.Errorf("The ServerGroup with PartnerId:%d, ServerId:%d should exist, but now it doesn't.", firstServer.PartnerId, firstServer.Id)
+ return
+ }
+}
+
+func TestResourceVersion(t *testing.T) {
+ list := GetResourceVersionList()
+ fmt.Printf("There are %d resource versions.\n", len(list))
+}
+
+func TestUserWhiteList(t *testing.T) {
+ fmt.Printf("There are %d whiteLists.\n", len(whiteListMap))
+ if len(whiteListMap) == 0 {
+ return
+ }
+
+ var partnerId int32
+ var userId string
+ for _, v := range whiteListMap {
+ for _, _v := range v {
+ partnerId = _v.PartnerId
+ userId = _v.UserId
+ break
+ }
+ break
+ }
+
+ expected := true
+ got := IsInWhiteList(partnerId, userId)
+ if got != expected {
+ t.Errorf("Expected to get %t, but got %t", expected, got)
+ return
+ }
+}
diff --git a/.svn/pristine/54/5445c6a66d28f994d025ce139e3a8e09bfb68196.svn-base b/.svn/pristine/54/5445c6a66d28f994d025ce139e3a8e09bfb68196.svn-base
new file mode 100644
index 0000000..5a8d915
--- /dev/null
+++ b/.svn/pristine/54/5445c6a66d28f994d025ce139e3a8e09bfb68196.svn-base
@@ -0,0 +1,16 @@
+package runtimeUtil
+
+import "runtime"
+
+// 获取当前正在使用的内存大小,单位:字节数
+// 具体参见文档:
+// 1. http://blog.csdn.net/webxscan/article/details/72857292
+// 2. https://studygolang.com/static/pkgdoc/pkg/runtime.htm#MemStats
+// 返回值:
+// int64:正在使用的内存大小
+func GetMemSize() uint64 {
+ var memStat runtime.MemStats
+ runtime.ReadMemStats(&memStat)
+
+ return memStat.Alloc
+}
diff --git a/.svn/pristine/54/54a0e682fd6262e24fa94fe5e10814532f88b5bf.svn-base b/.svn/pristine/54/54a0e682fd6262e24fa94fe5e10814532f88b5bf.svn-base
new file mode 100644
index 0000000..fc2e539
--- /dev/null
+++ b/.svn/pristine/54/54a0e682fd6262e24fa94fe5e10814532f88b5bf.svn-base
@@ -0,0 +1,247 @@
+package managecenterMgr
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "sort"
+
+ "Framework/ipMgr"
+ "Framework/managecenterModel"
+ . "Framework/managecenterModel"
+ "goutil/logUtil"
+ "goutil/webUtil"
+)
+
+var (
+ // 服务器组集合
+ serverGroupMap = make(map[int32]*ServerGroup, 512)
+ serverGroupHash string
+
+ // 服务器组变化方法集合 (完整列表,新增列表,删除列表,更新列表)
+ serverGroupChangeFuncMap = make(map[string]func([]*ServerGroup, []*ServerGroup, []*ServerGroup, []*ServerGroup))
+)
+
+func init() {
+ ipMgr.RegisterIpCheckFunc("ServerGroupIpCheck", isIpValid)
+}
+
+// 重新加载服务器组
+func reloadServerGroup(isInit bool) error {
+ //logUtil.DebugLog("开始刷新服务器组信息")
+
+ url := getManageCenterUrl("/API/ServerGroupList.ashx")
+
+ // 定义请求参数
+ postDict := make(map[string]string)
+ postDict["GroupType"] = "Mix"
+ postDict["HashValue"] = serverGroupHash
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, transport)
+ //statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, nil)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错,url:%s,错误信息为:%s", url, err))
+ return err
+ }
+ if statusCode != 200 {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错,url:%s,错误码为:%d", url, statusCode))
+ return err
+ }
+
+ // 解析返回值
+ returnObj := new(ReturnObject)
+ if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错,反序列化返回值出错,错误信息为:%s", err))
+ return err
+ }
+
+ // 判断返回状态是否为成功
+ if returnObj.Code != 0 {
+ // 数据没有变化,所以没有获取到新的数据,不能算错误。
+ if returnObj.Code == 47 || returnObj.Message == "DataNotChanged" {
+ //如果本地集合为空,且数据又没变化时,重新初始化一下本地hash值
+ if len(serverGroupMap) == 0 {
+ serverGroupHash = ""
+ }
+ return nil
+ } else {
+ msg := fmt.Sprintf("获取服务器组列表出错,返回状态:%d,信息为:%s", returnObj.Code, returnObj.Message)
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ }
+ }
+
+ // 解析Data
+ tmpServerGroupList := make([]*ServerGroup, 0, 512)
+ if data, ok := returnObj.Data.(string); !ok {
+ msg := "获取服务器组列表出错,返回的数据不是string类型"
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ } else {
+ if err = json.Unmarshal([]byte(data), &tmpServerGroupList); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器组列表出错,反序列化数据出错,错误信息为:%s", err))
+ return err
+ }
+ }
+
+ //logUtil.DebugLog(fmt.Sprintf("刷新服务器组信息结束,服务器组数量:%d", len(tmpServerGroupList)))
+
+ tmpServerGroupMap := make(map[int32]*ServerGroup, 512)
+ for _, item := range tmpServerGroupList {
+ tmpServerGroupMap[item.Id] = item
+ }
+
+ // 处理服务器组是否变化情况
+ addList, deleteList, updateList := handleServerGroupChange(GetServerGroupMap(), tmpServerGroupMap)
+ triggerServerGroupChangeFunc(tmpServerGroupList, addList, deleteList, updateList)
+
+ // 赋值给最终的ServerGroupMap
+ serverGroupMap = tmpServerGroupMap
+ serverGroupHash = returnObj.HashValue
+
+ //通知变更
+ mcDataChangeCallBack(managecenterModel.ServerGroupData, isInit)
+
+ return nil
+}
+
+// 处理服务器组是否变化情况
+// originalServerGroupMap: 当前服务器组集合
+// newServerGroupMap: 新的服务器组集合
+func handleServerGroupChange(currServerGroupMap, newServerGroupMap map[int32]*ServerGroup) (
+ addList []*ServerGroup, deleteList []*ServerGroup, updateList []*ServerGroup) {
+
+ // 判断是否有新增的数据
+ for k, v := range newServerGroupMap {
+ if _, exist := currServerGroupMap[k]; !exist {
+ addList = append(addList, v)
+ }
+ }
+
+ // 判断是否有删除的数据
+ for k, v := range currServerGroupMap {
+ if _, exist := newServerGroupMap[k]; !exist {
+ deleteList = append(deleteList, v)
+ }
+ }
+
+ // 判断是否有更新的数据
+ for k, currItem := range currServerGroupMap {
+ if newItem, exist := newServerGroupMap[k]; exist {
+ if currItem.IsEqual(newItem) == false {
+ updateList = append(updateList, newItem)
+ }
+ }
+ }
+
+ return
+}
+
+// 触发服务器组变化的方法
+func triggerServerGroupChangeFunc(allList []*ServerGroup, addList []*ServerGroup, deleteList []*ServerGroup, updateList []*ServerGroup) {
+ // 如果有注册服务器组变化的方法
+ if len(serverGroupChangeFuncMap) > 0 {
+ for _, serverGroupChangeFunc := range serverGroupChangeFuncMap {
+ serverGroupChangeFunc(allList, addList, deleteList, updateList)
+ }
+ }
+}
+
+// 注册服务器组变化方法
+// funcName:方法名称
+// serverGroupChangeFunc:服务器组变化方法
+func RegisterServerGroupChangeFunc(funcName string, serverGroupChangeFunc func([]*ServerGroup, []*ServerGroup, []*ServerGroup, []*ServerGroup)) {
+ if _, exists := serverGroupChangeFuncMap[funcName]; exists {
+ panic(fmt.Errorf("RegisterServerGroupChange:%s已经存在,请检查", funcName))
+ }
+ serverGroupChangeFuncMap[funcName] = serverGroupChangeFunc
+
+ logUtil.DebugLog(fmt.Sprintf("注册服务器组变化方法 funcName:%s,当前共有%d个注册", funcName, len(serverGroupChangeFuncMap)))
+}
+
+// 获取服务器组集合
+// 返回值:
+// 服务器组集合
+func GetServerGroupMap() (retServerGroupMap map[int32]*ServerGroup) {
+ retServerGroupMap = make(map[int32]*ServerGroup, 128)
+ for k, v := range serverGroupMap {
+ retServerGroupMap[k] = v
+ }
+
+ return
+}
+
+// 获取服务器组列表
+// 返回值:
+// 服务器组列表
+func GetServerGroupList() (serverGroupList []*ServerGroup) {
+ for _, item := range serverGroupMap {
+ serverGroupList = append(serverGroupList, item)
+ }
+
+ sort.Slice(serverGroupList, func(i, j int) bool {
+ return serverGroupList[i].SortByIdAsc(serverGroupList[j])
+ })
+
+ return
+}
+
+// 获取服务器组项
+// id
+// 返回值:
+// 服务器组对象
+// 是否存在
+func GetServerGroupItem(id int32) (serverGroupObj *ServerGroup, exist bool) {
+ serverGroupObj, exist = serverGroupMap[id]
+ return
+}
+
+// 根据合作商Id、服务器Id获取服务器组对象
+// partnerId:合作商Id
+// serverId:服务器Id
+// 返回值:
+// 服务器组对象
+// 服务器对象
+// 是否存在
+func GetServerGroup(partnerId, serverId int32) (serverGroupObj *ServerGroup, serverObj *Server, exist bool) {
+ var partnerObj *Partner
+
+ // 获取合作商对象
+ partnerObj, exist = GetPartner(partnerId)
+ if !exist {
+ return
+ }
+
+ // 获取服务器对象
+ serverObj, exist = GetServer(partnerObj, serverId)
+ if !exist {
+ return
+ }
+
+ // 获取服务器组对象
+ serverGroupObj, exist = GetServerGroupItem(serverObj.GroupId)
+ return
+}
+
+// 判断IP是否有效
+// ip:指定IP地址
+// 返回值:
+// IP是否有效
+func isIpValid(ip string) (exist bool) {
+ for _, v := range serverGroupMap {
+ for _, item := range v.GetIPList() {
+ if ip == item {
+ exist = true
+ return
+ }
+ }
+ }
+
+ return
+}
diff --git a/.svn/pristine/54/54b903c8c997feaac3b622c39ef0886b149d80e8.svn-base b/.svn/pristine/54/54b903c8c997feaac3b622c39ef0886b149d80e8.svn-base
new file mode 100644
index 0000000..b2e1aaa
--- /dev/null
+++ b/.svn/pristine/54/54b903c8c997feaac3b622c39ef0886b149d80e8.svn-base
@@ -0,0 +1,41 @@
+package webUtil
+
+import (
+ "testing"
+)
+
+func TestGetWebData(t *testing.T) {
+ weburl := "http://www.baidu.com"
+ resp, err := GetWebData(weburl, nil)
+ if err != nil {
+ t.Errorf("测试错误,返回的结果为:%s", err)
+ }
+
+ if len(resp) == 0 {
+ t.Errorf("返回的数据为空,期望不为空")
+ }
+}
+
+func TestGetWebData2(t *testing.T) {
+ weburl := "http://www.baidu.com"
+ data := make(map[string]string)
+ status, resp, err := GetWebData2(weburl, data, nil, nil)
+ if status != 200 || err != nil {
+ t.Errorf("Test failed. status:%d, err:%s", status, err)
+ }
+
+ if len(resp) == 0 {
+ t.Errorf("The result is empty, but we expect not empty")
+ }
+
+ data["Name"] = "Jordan"
+ data["Age"] = "32"
+ status, resp, err = GetWebData2(weburl, data, nil, nil)
+ if status != 200 || err != nil {
+ t.Errorf("Test failed. status:%d, err:%s", status, err)
+ }
+
+ if len(resp) == 0 {
+ t.Errorf("The result is empty, but we expect not empty")
+ }
+}
diff --git a/.svn/pristine/54/54fbc9bfaa37789ec76a10782c878db5e00b7e43.svn-base b/.svn/pristine/54/54fbc9bfaa37789ec76a10782c878db5e00b7e43.svn-base
new file mode 100644
index 0000000..1be16f4
--- /dev/null
+++ b/.svn/pristine/54/54fbc9bfaa37789ec76a10782c878db5e00b7e43.svn-base
@@ -0,0 +1,26 @@
+package qirui
+
+import (
+ "fmt"
+
+ "goutil/webUtil"
+)
+
+const (
+ SEND_MESSAGE_URL = "http://api.qirui.com:7891/mt"
+)
+
+func SendMessage(apiKey, apiSecret, mobile, message string) (bool, error) {
+ smsUrl := fmt.Sprintf("%s?dc=15&un=%s&pw=%s&da=%s&sm=%s&tf=3&rf=2&rd=1", SEND_MESSAGE_URL, apiKey, apiSecret, mobile, message)
+ status, resp, err := webUtil.GetWebData3(smsUrl, "", webUtil.GetJsonHeader(), nil)
+ if err != nil {
+ return false, err
+ }
+
+ if status != 200 {
+ return false, fmt.Errorf("StatusCode is %d", status)
+ }
+
+ fmt.Printf("qirui.SendMessage:%s, %s, %s\n", mobile, message, string(resp))
+ return true, nil
+}
diff --git a/.svn/pristine/55/55d454d62218b6c17d558654dfe26659205489a0.svn-base b/.svn/pristine/55/55d454d62218b6c17d558654dfe26659205489a0.svn-base
new file mode 100644
index 0000000..3c68c5b
--- /dev/null
+++ b/.svn/pristine/55/55d454d62218b6c17d558654dfe26659205489a0.svn-base
@@ -0,0 +1,15 @@
+package securityUtil
+
+import (
+ "testing"
+)
+
+func TestSha256(t *testing.T) {
+ source := "oauthConsumerKey=1Nocz0wk0Hi8oGgSosogC4K4k&oauthToken=TOKEN_%2B8vQAR1eoD3ujiGstjzdyakEgbkyvWhfzF1fChQJ46EH07n%2FQvrazkMqy%2BhuprqU&oauthSignatureMethod=HMAC-SHA1&oauthTimestamp=1508486834&oauthNonce=5409983431934290948&oauthVersion=1.0&"
+ sign := "813c8202a31c73371ae0bbe13cb49d65c94da3de2877345603271ca14e5e4bcd"
+
+ result := Sha256String(source, false)
+ if result != sign {
+ t.Fatalf("Sha256编码结果不一致")
+ }
+}
diff --git a/.svn/pristine/55/55d4f6929df5269adfb1bb29dba1fb1b34ce16bd.svn-base b/.svn/pristine/55/55d4f6929df5269adfb1bb29dba1fb1b34ce16bd.svn-base
new file mode 100644
index 0000000..b64025d
--- /dev/null
+++ b/.svn/pristine/55/55d4f6929df5269adfb1bb29dba1fb1b34ce16bd.svn-base
@@ -0,0 +1,99 @@
+package sqlSync
+
+import (
+ "database/sql"
+ "fmt"
+ "strings"
+ "time"
+
+ "goutil/logUtil"
+)
+
+// 以事务的方式执行
+// db:数据库对象
+// funcObj:对应的具体处理函数
+// 返回值:
+// error:处理是否存在错误
+func ExecuteByTran(db *sql.DB, funcObj func(tran *sql.Tx) (isCommit bool, err error)) error {
+ tran, err := db.Begin()
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("start transaction error:%v", err.Error()))
+ return err
+ }
+
+ // 事务处理
+ isCommit := false
+ defer func() {
+ if isCommit {
+ err = tran.Commit()
+ } else {
+ err = tran.Rollback()
+ }
+
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("transaction end error:%v", err.Error()))
+ }
+ }()
+
+ isCommit, err = funcObj(tran)
+
+ return err
+}
+
+// 循环执行知道返回成功为止
+// funcObj:待执行的函数
+// interval:执行间隔时间
+func WaitForOk(funcObj func() bool, interval time.Duration) {
+ for {
+ if funcObj() == false {
+ time.Sleep(interval)
+ }
+
+ break
+ }
+}
+
+// 检查是否是连接错误
+// errMsg:错误信息
+// 返回值:
+// bool:true:连接错误 false:其他异常
+func CheckIfConnectionError(errMsg string) bool {
+ //// 连接被关闭
+ ifConnectionClose := strings.Contains(errMsg, "A connection attempt failed because the connected party did not properly respond")
+ if ifConnectionClose {
+ return true
+ }
+
+ // 使用过程中连接断开
+ ifConnectionClose = strings.Contains(errMsg, "No connection could be made")
+ if ifConnectionClose {
+ return true
+ }
+
+ // 事务处理过程中连接断开的提示
+ ifConnectionClose = strings.Contains(errMsg, "bad connection")
+ if ifConnectionClose {
+ return true
+ }
+
+ // socket压根儿连不上的处理
+ ifConnectionClose = strings.Contains(errMsg, "A socket operation was attempted to an unreachable network")
+ if ifConnectionClose {
+ return true
+ }
+
+ // 用户无法访问
+ return strings.Contains(errMsg, "Access denied for user")
+}
+
+// 获取比较简洁的错误信息
+// errMsg:错误信息
+// 返回值:
+// string:比较简洁的错误信息
+func GetSimpleErrorMessage(errMsg string) string {
+ if strings.Contains(errMsg, "Error 1064: You have an error in your SQL syntax") {
+ return "SqlError"
+ }
+
+ return errMsg
+}
diff --git a/.svn/pristine/56/56917ecd3dd2f5232b9c9c3ca1dcfaed71e2c9bb.svn-base b/.svn/pristine/56/56917ecd3dd2f5232b9c9c3ca1dcfaed71e2c9bb.svn-base
new file mode 100644
index 0000000..62b18ea
--- /dev/null
+++ b/.svn/pristine/56/56917ecd3dd2f5232b9c9c3ca1dcfaed71e2c9bb.svn-base
@@ -0,0 +1,91 @@
+package stringUtil
+
+import (
+ "testing"
+)
+
+func TestSimilarity(t *testing.T) {
+ source := ""
+ target := ""
+ expectedDistance := 0
+ expectedSimilarity := 0.0
+ gotDistance, gotSimilarity := Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+
+ source = "Hello"
+ target = ""
+ expectedDistance = 5
+ expectedSimilarity = 0.0
+ gotDistance, gotSimilarity = Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+
+ source = ""
+ target = "Hello"
+ expectedDistance = 5
+ expectedSimilarity = 0.0
+ gotDistance, gotSimilarity = Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+
+ source = "Helo"
+ target = "Hello"
+ expectedDistance = 1
+ expectedSimilarity = 4.0 / 5.0
+ gotDistance, gotSimilarity = Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+
+ source = "kitten"
+ target = "sitten"
+ expectedDistance = 1
+ expectedSimilarity = 5.0 / 6.0
+ gotDistance, gotSimilarity = Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+
+ source = "Michael Jordan"
+ target = "Michael Jordan"
+ expectedDistance = 0
+ expectedSimilarity = 1
+ gotDistance, gotSimilarity = Similarity(source, target)
+ if gotDistance != expectedDistance {
+ t.Errorf("Expected to get %d, now got %d", expectedDistance, gotDistance)
+ return
+ }
+ if gotSimilarity != expectedSimilarity {
+ t.Errorf("Expected to get %f, now got %f", expectedSimilarity, gotSimilarity)
+ return
+ }
+}
diff --git a/.svn/pristine/56/56f885374bb697f0fe69c523d081a0ef9645d4bf.svn-base b/.svn/pristine/56/56f885374bb697f0fe69c523d081a0ef9645d4bf.svn-base
new file mode 100644
index 0000000..3d317b0
--- /dev/null
+++ b/.svn/pristine/56/56f885374bb697f0fe69c523d081a0ef9645d4bf.svn-base
@@ -0,0 +1,32 @@
+package securityUtil
+
+import (
+ "testing"
+)
+
+func TestSha1String(t *testing.T) {
+ s := "hello world"
+ result := Sha1String(s, true)
+ if result != "2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED" {
+ t.Errorf("Sha1String(\"hello world\") failed.Got %s, expected %s", result, "2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED")
+ }
+
+ result = Sha1String(s, false)
+ if result != "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed" {
+ t.Errorf("Sha1String(\"hello world\") failed.Got %s, expected %s", result, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")
+ }
+}
+
+func TestSha1Bytes(t *testing.T) {
+ s := "hello world"
+ b := []byte(s)
+ result := Sha1Bytes(b, true)
+ if result != "2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED" {
+ t.Errorf("Sha1Bytes(\"hello world\") failed.Got %s, expected %s", result, "2AAE6C35C94FCFB415DBE95F408B9CE91EE846ED")
+ }
+
+ result = Sha1Bytes(b, false)
+ if result != "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed" {
+ t.Errorf("Sha1Bytes(\"hello world\") failed.Got %s, expected %s", result, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")
+ }
+}
diff --git a/.svn/pristine/57/576810f1d094644512c078a85a8cf10b20959f04.svn-base b/.svn/pristine/57/576810f1d094644512c078a85a8cf10b20959f04.svn-base
new file mode 100644
index 0000000..964cfe6
--- /dev/null
+++ b/.svn/pristine/57/576810f1d094644512c078a85a8cf10b20959f04.svn-base
@@ -0,0 +1,81 @@
+// ************************************
+// @package: handleMgr
+// @description: 全局操作接口管理API类
+// @author:
+// @revision history:
+// @create date: 2022-02-23 16:24:59
+// ************************************
+
+package handleMgr
+
+/*
+用于提供全局操作接口管理API类
+*/
+
+/*
+接口说明
+
+接口1:
+// RegisterNewModule
+// @description: 注册方法
+// parameter:
+// @moduleName:模块名
+// @structObject:模块对象
+// @monitorTime:监控日志超时时间,传入0是用默认值100
+// return:
+
+示例:RegisterNewModule("test", new(testBll), 0)
+
+接口2:
+// Done
+// @description: 执行访问
+// parameter:
+// @logicalId:逻辑实例Id-同一串行错误类的唯一标识
+// @moduleName:模块名
+// @funcName:执行方法名称
+// @parameter:方法参数
+// @isHaveResult:是否处理返回值
+// return:
+// @data:返还对象
+// @code:错误码-0未无错误
+// @message:错误说明-空字符串为无错误
+
+示例:data,code,mes := Done("test", "testBll", "Add", parameter, false)
+
+注意:
+注册的类实现的方法返回值必须是*ResponseObject为返回对象
+示例:
+
+type testBll struct {
+}
+
+// TestAdd
+// @description:测试添加
+// parameter:
+// @receiver t:
+// @x:
+// @y:
+// return:
+// @*ResponseObject:
+func (t testBll) TestAdd(x, y int) *ResponseObject {
+ responseObj := GetInitResponseObj()
+ data[x] = y
+ z := x + y
+
+ responseObj.SetData(z)
+ responseObj.SetResultStatus("错误码")
+ return responseObj
+}
+
+func TestNew(t *testing.T) {
+ // 注册类
+ RegisterNewModule("test", new(testBll), 10)
+
+ // 调用方法
+ data, code, mes := Done("test", "testBll", "TestAdd", parameter, false)
+
+ // 可以重复注册多个类,逻辑实例Id保持一致即可
+ RegisterNewModule("test", new(test2Bll), 10)
+ data, code, mes := Done("test", "test2Bll", "TestAdd", parameter, false)
+}
+*/
diff --git a/.svn/pristine/57/57ed580996c3cd3c94a7b7422b369a6540ad167a.svn-base b/.svn/pristine/57/57ed580996c3cd3c94a7b7422b369a6540ad167a.svn-base
new file mode 100644
index 0000000..90a70e3
--- /dev/null
+++ b/.svn/pristine/57/57ed580996c3cd3c94a7b7422b369a6540ad167a.svn-base
@@ -0,0 +1,198 @@
+package stringUtil
+
+// 表情符号集合
+var emojiData map[rune]rune
+
+func init() {
+ emojiData = make(map[rune]rune, 1024)
+
+ addEmojiChar()
+}
+
+// 添加一个范围的unicode
+// start:unicode起始位置
+// endlist:unicode结束位置
+func addUnicodeRange(start rune, endlist ...rune) {
+ if len(endlist) <= 0 {
+ // 添加单个的
+ emojiData[start] = start
+ return
+ }
+
+ end := endlist[0]
+ if start > end {
+ return
+ }
+
+ // 添加范围的
+ for i := start; i <= end; i++ {
+ emojiData[i] = i
+ }
+}
+
+// 增加emoji表情符号
+// 表情字符大全参考:
+// https://zh.wikipedia.org/wiki/%E7%B9%AA%E6%96%87%E5%AD%97
+// 对应unicode版本号:Unicode 10.0版本
+func addEmojiChar() {
+ addUnicodeRange(0x00A9)
+ addUnicodeRange(0x00AE)
+
+ addUnicodeRange(0x203C)
+ addUnicodeRange(0x2049)
+ addUnicodeRange(0x2122)
+ addUnicodeRange(0x2139)
+ addUnicodeRange(0x2194, 0x2199)
+ addUnicodeRange(0x21A9, 0x21AA)
+ addUnicodeRange(0x231A, 0x231B)
+ addUnicodeRange(0x2328)
+ addUnicodeRange(0x23CF)
+ addUnicodeRange(0x23E9, 0x23F3)
+ addUnicodeRange(0x23F8, 0x23FA)
+ addUnicodeRange(0x24C2)
+ addUnicodeRange(0x25AA, 0x25AB)
+ addUnicodeRange(0x25B6)
+ addUnicodeRange(0x25C0)
+ addUnicodeRange(0x25FB, 0x25FE)
+
+ addUnicodeRange(0x2600, 0x2604)
+ addUnicodeRange(0x260E)
+ addUnicodeRange(0x2611)
+ addUnicodeRange(0x2614, 0x2615)
+ addUnicodeRange(0x2618)
+ addUnicodeRange(0x261D)
+ addUnicodeRange(0x2620)
+ addUnicodeRange(0x2622, 0x2623)
+ addUnicodeRange(0x2626)
+ addUnicodeRange(0x262A)
+ addUnicodeRange(0x262E, 0x262F)
+ addUnicodeRange(0x2638, 0x263A)
+ addUnicodeRange(0x2640)
+ addUnicodeRange(0x2642)
+ addUnicodeRange(0x2648, 0x2653)
+ addUnicodeRange(0x2660)
+ addUnicodeRange(0x2663)
+ addUnicodeRange(0x2665, 0x2666)
+ addUnicodeRange(0x2668)
+ addUnicodeRange(0x267B)
+ addUnicodeRange(0x267F)
+ addUnicodeRange(0x2692, 0x2697)
+ addUnicodeRange(0x2699)
+ addUnicodeRange(0x269B, 0x269C)
+
+ addUnicodeRange(0x26A0, 0x26A1)
+ addUnicodeRange(0x26AA, 0x26AB)
+ addUnicodeRange(0x26B0, 0x26B1)
+ addUnicodeRange(0x26BD, 0x26BE)
+ addUnicodeRange(0x26C4, 0x26C5)
+ addUnicodeRange(0x26C8)
+ addUnicodeRange(0x26CE, 0x26CF)
+ addUnicodeRange(0x26D1)
+ addUnicodeRange(0x26D3, 0x26D4)
+ addUnicodeRange(0x26E9, 0x26EA)
+ addUnicodeRange(0x26F0, 0x26F5)
+ addUnicodeRange(0x26F7, 0x26FA)
+ addUnicodeRange(0x26FD)
+
+ addUnicodeRange(0x2702)
+ addUnicodeRange(0x2705)
+ addUnicodeRange(0x2708, 0x270D)
+ addUnicodeRange(0x270F)
+ addUnicodeRange(0x2712)
+ addUnicodeRange(0x2714)
+ addUnicodeRange(0x2716)
+ addUnicodeRange(0x271D)
+ addUnicodeRange(0x2721)
+ addUnicodeRange(0x2728)
+ addUnicodeRange(0x2733, 0x2734)
+ addUnicodeRange(0x2744)
+ addUnicodeRange(0x2747)
+ addUnicodeRange(0x274C)
+ addUnicodeRange(0x274E)
+ addUnicodeRange(0x2753, 0x2755)
+ addUnicodeRange(0x2757)
+ addUnicodeRange(0x2763, 0x2764)
+ addUnicodeRange(0x2795, 0x2797)
+ addUnicodeRange(0x27A1)
+ addUnicodeRange(0x27B0)
+ addUnicodeRange(0x27BF)
+ addUnicodeRange(0x2934, 0x2935)
+ addUnicodeRange(0x2B05, 0x2B07)
+ addUnicodeRange(0x2B1B, 0x2B1C)
+ addUnicodeRange(0x2B50)
+ addUnicodeRange(0x2B55)
+ addUnicodeRange(0x3030)
+ addUnicodeRange(0x303D)
+ addUnicodeRange(0x3297, 0x3299)
+ addUnicodeRange(0x3299)
+ addUnicodeRange(0x1F004)
+ addUnicodeRange(0x1F0CF)
+ addUnicodeRange(0x1F170, 0x1F171)
+ addUnicodeRange(0x1F17E, 0x1F17F)
+ addUnicodeRange(0x1F18E)
+
+ addUnicodeRange(0x1F191, 0x1F19A)
+ addUnicodeRange(0x1F201, 0x1F202)
+ addUnicodeRange(0x1F21A)
+ addUnicodeRange(0x1F22F)
+ addUnicodeRange(0x1F232, 0x1F23A)
+ addUnicodeRange(0x1F250, 0x1F251)
+ addUnicodeRange(0x1F300, 0x1F321)
+ addUnicodeRange(0x1F324, 0x1F393)
+ addUnicodeRange(0x1F396, 0x1F397)
+ addUnicodeRange(0x1F399, 0x1F39B)
+ addUnicodeRange(0x1F39E, 0x1F3F0)
+ addUnicodeRange(0x1F3F3, 0x1F3F5)
+ addUnicodeRange(0x1F3F7, 0x1F53D)
+
+ addUnicodeRange(0x1F549, 0x1F54E)
+ addUnicodeRange(0x1F550, 0x1F567)
+ addUnicodeRange(0x1F56F, 0x1F570)
+ addUnicodeRange(0x1F573, 0x1F57A)
+ addUnicodeRange(0x1F587)
+ addUnicodeRange(0x1F58A, 0x1F58D)
+ addUnicodeRange(0x1F590)
+ addUnicodeRange(0x1F595, 0x1F596)
+ addUnicodeRange(0x1F5A4, 0x1F5A5)
+ addUnicodeRange(0x1F5A8)
+ addUnicodeRange(0x1F5B1, 0x1F5B2)
+ addUnicodeRange(0x1F5BC)
+ addUnicodeRange(0x1F5C2, 0x1F5C4)
+ addUnicodeRange(0x1F5D1, 0x1F5D3)
+ addUnicodeRange(0x1F5DC, 0x1F5DE)
+ addUnicodeRange(0x1F5E1)
+ addUnicodeRange(0x1F5E3)
+ addUnicodeRange(0x1F5E8)
+ addUnicodeRange(0x1F5EF)
+ addUnicodeRange(0x1F5F3)
+ addUnicodeRange(0x1F5FA, 0x1F6C5)
+ addUnicodeRange(0x1F6CB, 0x1F6D2)
+ addUnicodeRange(0x1F6E0, 0x1F6E5)
+ addUnicodeRange(0x1F6E8)
+ addUnicodeRange(0x1F6EB, 0x1F6EC)
+ addUnicodeRange(0x1F6F0)
+ addUnicodeRange(0x1F6F3, 0x1F6F8)
+ addUnicodeRange(0x1F910, 0x1F93A)
+ addUnicodeRange(0x1F93B, 0x1F93E)
+ addUnicodeRange(0x1F940, 0x1F945)
+ addUnicodeRange(0x1F947, 0x1F94C)
+ addUnicodeRange(0x1F950, 0x1F96B)
+ addUnicodeRange(0x1F980, 0x1F997)
+ addUnicodeRange(0x1F9C0)
+ addUnicodeRange(0x1F9D0, 0x1F9E6)
+}
+
+// 检查是否含有表情字符
+// val:待查看的字符串
+// 返回值:
+// 是否包含有表情字符
+func IfHaveEmoji(val string) bool {
+ // 由于golang在内存中本来就是使用的Unicode,所以可以直接进行匹配操作
+ for _, charItem := range val {
+ if _, eixst := emojiData[charItem]; eixst {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/.svn/pristine/58/587f9e024e52f1a9c27470de900d08085d5fc9d1.svn-base b/.svn/pristine/58/587f9e024e52f1a9c27470de900d08085d5fc9d1.svn-base
new file mode 100644
index 0000000..567adf9
--- /dev/null
+++ b/.svn/pristine/58/587f9e024e52f1a9c27470de900d08085d5fc9d1.svn-base
@@ -0,0 +1,20 @@
+package mailUtil
+
+import (
+ "testing"
+)
+
+func TestSendMail(t *testing.T) {
+ svr := SimpleSMTPClient("smtp.exmail.qq.com", 465, true, "name", "service@public.com", "Sv123456")
+ err := svr.SendMail([]string{"164760769@qq.com"},
+ "邮件发送测试",
+ "这是邮件正文
",
+ true,
+ []string{
+ "./doc.go",
+ "./simpleClient_test.go",
+ })
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/.svn/pristine/59/5921c843b6a9a0d075c29e4af206bb73d7e042a4.svn-base b/.svn/pristine/59/5921c843b6a9a0d075c29e4af206bb73d7e042a4.svn-base
new file mode 100644
index 0000000..e9637bc
--- /dev/null
+++ b/.svn/pristine/59/5921c843b6a9a0d075c29e4af206bb73d7e042a4.svn-base
@@ -0,0 +1,860 @@
+package redisUtil
+
+import (
+ "testing"
+ "time"
+)
+
+var (
+ redisPoolObj_db *RedisPool
+)
+
+func init() {
+ redisPoolObj_db = NewRedisPool("testPool", "10.1.0.21:6379", "redis_pwd", 5, 500, 200, 10*time.Second, 5*time.Second)
+}
+
+func TestExists(t *testing.T) {
+ /*
+ redis> SET db "redis"
+ OK
+ */
+ key := "db"
+ value := "redis"
+ successful, err := redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set the key:%s should be successful, but now it's not.", key)
+ return
+ }
+
+ /*
+ redis> EXISTS db
+ (integer) 1
+ */
+ exist, err := redisPoolObj_db.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("Set the key:%s should exist, but now it doesn't.", key)
+ return
+ }
+
+ /*
+ redis> DEL db
+ (integer) 1
+ */
+ expected := 1
+ got, err := redisPoolObj_db.Del(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ /*
+ redis> EXISTS db
+ (integer) 0
+ */
+ exist, err = redisPoolObj_db.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("Set the key:%s should not exist, but now it does.", key)
+ return
+ }
+}
+
+func TestType(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 字符串
+
+ redis> SET weather "sunny"
+ OK
+
+ redis> TYPE weather
+ string
+ */
+ key := "weather"
+ value := "sunny"
+
+ successful, err := redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if !successful {
+ t.Errorf("Set the key:%s should be successful, but now it's not.", key)
+ return
+ }
+
+ expected := "string"
+ got, err := redisPoolObj_db.Type(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 列表
+
+ redis> LPUSH book_list "programming in scala"
+ (integer) 1
+
+ redis> TYPE book_list
+ list
+ */
+ key = "book_list"
+ value = "programming in scala"
+ expected2 := 1
+ got2, err := redisPoolObj_db.LPush(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d", expected2, got2)
+ return
+ }
+
+ expected = "list"
+ got, err = redisPoolObj_db.Type(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+
+ /*
+ # 集合
+
+ redis> SADD pat "dog"
+ (integer) 1
+
+ redis> TYPE pat
+ set
+ */
+
+ key = "pat"
+ value = "dog"
+ expected3 := 1
+ got3, err := redisPoolObj_db.SAdd(key, value)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d", expected3, got3)
+ return
+ }
+
+ expected = "set"
+ got, err = redisPoolObj_db.Type(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, key)
+}
+
+func TestRename(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # key 存在且 newkey 不存在
+
+ redis> SET message "hello world"
+ OK
+
+ redis> RENAME message greeting
+ OK
+
+ redis> EXISTS message # message 不复存在
+ (integer) 0
+
+ redis> EXISTS greeting # greeting 取而代之
+ (integer) 1
+ */
+ key := "message"
+ value := "hello world"
+ expected := true
+ got, err := redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ newkey := "greeting"
+ err = redisPoolObj_db.Rename(key, newkey)
+ if err != nil {
+ t.Fail()
+ }
+
+ expected = false
+ got, err = redisPoolObj_db.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected = true
+ got, err = redisPoolObj_db.Exists(newkey)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, newkey)
+
+ /*
+ # 当 key 不存在时,返回错误
+
+ redis> RENAME fake_key never_exists
+ (error) ERR no such key
+ */
+ key = "fake_key"
+ newkey = "never_exists"
+ err = redisPoolObj_db.Rename(key, newkey)
+ if err == nil {
+ t.Errorf("There should be one error, but now there isn't.")
+ return
+ }
+
+ /*
+ # newkey 已存在时, RENAME 会覆盖旧 newkey
+
+ redis> SET pc "lenovo"
+ OK
+
+ redis> SET personal_computer "dell"
+ OK
+
+ redis> RENAME pc personal_computer
+ OK
+
+ redis> GET pc
+ (nil)
+
+ redis:1> GET personal_computer # 原来的值 dell 被覆盖了
+ "lenovo"
+ */
+ key = "pc"
+ value = "lenovo"
+ expected = true
+ got, err = redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ key = "personal_computer"
+ value = "dell"
+ expected = true
+ got, err = redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ key = "pc"
+ newkey = "personal_computer"
+ err = redisPoolObj_db.Rename(key, newkey)
+ if err != nil {
+ t.Fail()
+ }
+
+ expected = false
+ got, err = redisPoolObj_db.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected = true
+ got, err = redisPoolObj_db.Exists(newkey)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, newkey)
+}
+
+func TestRenameNX(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_string.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # newkey 不存在,改名成功
+
+ redis> SET player "MPlyaer"
+ OK
+
+ redis> EXISTS best_player
+ (integer) 0
+
+ redis> RENAMENX player best_player
+ (integer) 1
+ */
+ key := "player"
+ value := "MPlayer"
+ expected := true
+ got, err := redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ newkey := "best_player"
+ expected = false
+ got, err = redisPoolObj_db.Exists(newkey)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected = true
+ got, err = redisPoolObj_db.RenameNX(key, newkey)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ deleteKeys = append(deleteKeys, newkey)
+
+ /*
+ # newkey存在时,失败
+
+ redis> SET animal "bear"
+ OK
+
+ redis> SET favorite_animal "butterfly"
+ OK
+
+ redis> RENAMENX animal favorite_animal
+ (integer) 0
+
+ redis> get animal
+ "bear"
+
+ redis> get favorite_animal
+ "butterfly"
+ */
+ key = "animal"
+ value = "bear"
+ expected = true
+ got, err = redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ key = "favorite_animal"
+ value = "butterfly"
+ expected = true
+ got, err = redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+ deleteKeys = append(deleteKeys, key)
+
+ expected = false
+ got, err = redisPoolObj_db.RenameNX(key, newkey)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ key2 := "animal"
+ expected2 := "bear"
+ got2_interface, exist2, err := redisPoolObj_db.Get(key2)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist2 {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key2)
+ return
+ }
+ got2, err := redisPoolObj_db.String(got2_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %s, but now got %s", expected2, got2)
+ return
+ }
+
+ key3 := "animal"
+ expected3 := "bear"
+ got3_interface, exist3, err := redisPoolObj_db.Get(key3)
+ if err != nil {
+ t.Fail()
+ }
+ if !exist3 {
+ t.Errorf("The key:%s should exist, but now it doesn't.", key3)
+ return
+ }
+ got3, err := redisPoolObj_db.String(got3_interface)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %s, but now got %s", expected3, got3)
+ return
+ }
+}
+
+func TestDel(t *testing.T) {
+ /*
+ # 删除单个 key
+
+ redis> SET name huangz
+ OK
+
+ redis> DEL name
+ (integer) 1
+ */
+ key := "name"
+ value := "huangz"
+ expected := true
+ got, err := redisPoolObj_db.Set(key, value, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected2 := 1
+ got2, err := redisPoolObj_db.Del(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got2 != expected2 {
+ t.Errorf("Expected to get %d, but now got %d", expected2, got2)
+ return
+ }
+
+ /*
+ # 删除一个不存在的 key
+
+ redis> EXISTS phone
+ (integer) 0
+
+ redis> DEL phone # 失败,没有 key 被删除
+ (integer) 0
+ */
+ key = "phone"
+ expected = false
+ got, err = redisPoolObj_db.Exists(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected3 := 0
+ got3, err := redisPoolObj_db.Del(key)
+ if err != nil {
+ t.Fail()
+ }
+ if got3 != expected3 {
+ t.Errorf("Expected to get %d, but now got %d", expected3, got3)
+ return
+ }
+
+ /*
+ # 同时删除多个 key
+
+ redis> SET name "redis"
+ OK
+
+ redis> SET type "key-value store"
+ OK
+
+ redis> SET website "redis.com"
+ OK
+
+ redis> DEL name type website
+ (integer) 3
+ */
+ key1 := "name"
+ value1 := "redis"
+ expected = true
+ got, err = redisPoolObj_db.Set(key1, value1, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+ key2 := "type"
+ value2 := "key-value store"
+ expected = true
+ got, err = redisPoolObj_db.Set(key2, value2, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+ key3 := "website"
+ value3 := "redis.com"
+ expected = true
+ got, err = redisPoolObj_db.Set(key3, value3, "", 0, "")
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %t, but now got %t", expected, got)
+ return
+ }
+
+ expected4 := 3
+ got4, err := redisPoolObj_db.Del(key1, key2, key3)
+ if err != nil {
+ t.Fail()
+ }
+ if got4 != expected4 {
+ t.Errorf("Expected to get %d, but now got %d", expected4, got4)
+ return
+ }
+}
+
+func TestRandomKey(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ # 数据库为空
+
+ redis> RANDOMKEY
+ (nil)
+ */
+ expected := ""
+ got, exist, err := redisPoolObj_db.RandomKey()
+ if err != nil {
+ t.Fail()
+ }
+ if exist {
+ t.Errorf("RandomKey doesn't exist, but now it does.")
+ return
+ }
+ if got != expected {
+ t.Errorf("Expected to get %s, but now got %s", expected, got)
+ return
+ }
+
+ /*
+ # 数据库不为空
+
+ redis> MSET fruit "apple" drink "beer" food "cookies" # 设置多个 key
+ OK
+
+ redis> RANDOMKEY
+ "fruit"
+
+ redis> RANDOMKEY
+ "food"
+
+ redis> KEYS * # 查看数据库内所有key,证明 RANDOMKEY 并不删除 key
+ 1) "food"
+ 2) "drink"
+ 3) "fruit"
+ */
+ key_value_map := make(map[string]interface{})
+ key_value_map["fruit"] = "apple"
+ key_value_map["drink"] = "beer"
+ key_value_map["food"] = "cookies"
+ err = redisPoolObj_db.MSet(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ got, exist, err = redisPoolObj_db.RandomKey()
+ if err != nil {
+ t.Fail()
+ }
+ if !exist {
+ t.Errorf("RandomKey should exist, but now it doesn't.")
+ return
+ }
+ if _, exist = key_value_map[got]; !exist {
+ t.Errorf("RandomKey should exist, but now it doesn't.")
+ return
+ }
+
+ expected2 := make([]string, 0, len(key_value_map))
+ for k := range key_value_map {
+ expected2 = append(expected2, k)
+ deleteKeys = append(deleteKeys, k)
+ }
+ got2, err := redisPoolObj_db.Keys("*")
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected2, got2) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected2, got2)
+ return
+ }
+}
+
+func TestDBSize(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> DBSIZE
+ (integer) 0
+
+ redis> SET new_key "hello_moto" # 增加一个 key 试试
+ OK
+
+ redis> DBSIZE
+ (integer) 1
+ */
+ expected := 0
+ got, err := redisPoolObj_db.DBSize()
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+
+ key := "new_key"
+ value := "hello_moto"
+ redisPoolObj_db.Set(key, value, "", 0, "")
+
+ deleteKeys = append(deleteKeys, key)
+
+ expected = 1
+ got, err = redisPoolObj_db.DBSize()
+ if err != nil {
+ t.Fail()
+ }
+ if got != expected {
+ t.Errorf("Expected to get %d, but now got %d", expected, got)
+ return
+ }
+}
+
+func TestKeys(t *testing.T) {
+ deleteKeys := make([]string, 0, 8)
+ defer func() {
+ // Delete the test keys
+ distinctKeyList := getDistinctKeyList(deleteKeys)
+ count, err := redisPoolObj_list.Del(distinctKeyList...)
+ if err != nil {
+ t.Fail()
+ }
+ if count != len(distinctKeyList) {
+ t.Errorf("Expected to get %d, but now got %d", len(distinctKeyList), count)
+ return
+ }
+ }()
+
+ /*
+ redis> MSET one 1 two 2 three 3 four 4 # 一次设置 4 个 key
+ OK
+ */
+ key_value_map := make(map[string]interface{})
+ key_value_map["one"] = "1"
+ key_value_map["two"] = "2"
+ key_value_map["three"] = "3"
+ key_value_map["four"] = "4"
+ err := redisPoolObj_db.MSet(key_value_map)
+ if err != nil {
+ t.Fail()
+ }
+
+ for k := range key_value_map {
+ deleteKeys = append(deleteKeys, k)
+ }
+
+ /*
+ redis> KEYS *o*
+ 1) "four"
+ 2) "two"
+ 3) "one"
+ */
+ pattern := "*o*"
+ expected := []string{"four", "two", "one"}
+ got, err := redisPoolObj_db.Keys(pattern)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected, got) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected, got)
+ return
+ }
+
+ /*
+ redis> KEYS t??
+ 1) "two"
+ */
+ pattern = "t??"
+ expected = []string{"two"}
+ got, err = redisPoolObj_db.Keys(pattern)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected, got) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected, got)
+ return
+ }
+
+ /*
+ redis> KEYS t[w]*
+ 1) "two"
+ */
+ pattern = "t[w]*"
+ expected = []string{"two"}
+ got, err = redisPoolObj_db.Keys(pattern)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected, got) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected, got)
+ return
+ }
+
+ /*
+ redis> KEYS * # 匹配数据库内所有 key
+ 1) "four"
+ 2) "three"
+ 3) "two"
+ 4) "one"
+ */
+ pattern = "*"
+ expected = []string{"two", "one", "three", "four"}
+ got, err = redisPoolObj_db.Keys(pattern)
+ if err != nil {
+ t.Fail()
+ }
+ if isTwoUnorderedSliceEqual(expected, got) == false {
+ t.Errorf("Expected to get %v, but got %v\n", expected, got)
+ return
+ }
+}
diff --git a/.svn/pristine/59/59644769e5532c6fa13a4bdf8e311311407deff0.svn-base b/.svn/pristine/59/59644769e5532c6fa13a4bdf8e311311407deff0.svn-base
new file mode 100644
index 0000000..e01a089
--- /dev/null
+++ b/.svn/pristine/59/59644769e5532c6fa13a4bdf8e311311407deff0.svn-base
@@ -0,0 +1,400 @@
+package httpServer
+
+import (
+ config "common/configsYaml"
+ "common/resultStatus"
+ "common/webServer"
+ "goutil/logUtilPlus"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+const (
+ // 供客户端访问的模块的后缀
+ con_ModuleSuffix = "Module"
+
+ // 定义用于分隔模块名称和方法名称的分隔符
+ con_DelimeterOfObjAndMethod = "_"
+)
+
+var (
+ // 定义存放所有方法映射的变量
+ methodMap = make(map[string]*methodAndInOutTypes)
+
+ // 函数返回值类型
+ responseType reflect.Type = reflect.TypeOf(new(webServer.ResponseObject))
+)
+
+// getStructName
+// @description: 获取结构体类型的名称
+// parameter:
+// @structType: 结构体类型
+// return:
+// @string: 结构体类型的名称
+func getStructName(structType reflect.Type) string {
+ reflectTypeStr := structType.String()
+ reflectTypeArr := strings.Split(reflectTypeStr, ".")
+
+ return reflectTypeArr[len(reflectTypeArr)-1]
+}
+
+// getFullModuleName
+// @description: 获取完整的模块名称
+// parameter:
+// @moduleName: 模块名称
+// return:
+// @string: 完整的模块名称
+func getFullModuleName(moduleName string) string {
+ return moduleName + con_ModuleSuffix
+}
+
+// getFullMethodName
+// @description: 获取完整的方法名称
+// parameter:
+// @structName: 结构体名称
+// @methodName: 方法名称
+// return:
+// @string: 完整的方法名称
+func getFullMethodName(structName, methodName string) string {
+ return structName + con_DelimeterOfObjAndMethod + methodName
+}
+
+// resolveMethodInOutParams
+// @description: 解析方法的输入输出参数
+// parameter:
+// @method: 方法对应的反射值
+// return:
+// @inTypes: 输入参数类型集合
+// @outTypes: 输出参数类型集合
+func resolveMethodInOutParams(method reflect.Value) (inTypes []reflect.Type, outTypes []reflect.Type) {
+ methodType := method.Type()
+ for i := 0; i < methodType.NumIn(); i++ {
+ inTypes = append(inTypes, methodType.In(i))
+ }
+
+ for i := 0; i < methodType.NumOut(); i++ {
+ outTypes = append(outTypes, methodType.Out(i))
+ }
+
+ return
+}
+
+// RegisterFunction
+// @description: 将需要对客户端提供方法的对象进行注册
+// parameter:
+// @structObject: 对象
+// return:
+func RegisterFunction(structObject interface{}) {
+ // 获取structObject对应的反射 Type 和 Value
+ reflectValue := reflect.ValueOf(structObject)
+ reflectType := reflect.TypeOf(structObject)
+
+ // 提取对象类型名称
+ structName := getStructName(reflectType)
+
+ // 获取structObject中返回值为responseObject的方法
+ for i := 0; i < reflectType.NumMethod(); i++ {
+ // 获得方法名称
+ methodName := reflectType.Method(i).Name
+
+ // 获得方法及其输入参数的类型列表
+ method := reflectValue.MethodByName(methodName)
+ inTypes, outTypes := resolveMethodInOutParams(method)
+
+ // 判断输出参数数量是否正确
+ if len(outTypes) != 1 {
+ continue
+ }
+
+ // 判断返回值是否为responseObject
+ if outTypes[0] != responseType {
+ continue
+ }
+
+ // 添加到列表中
+ methodMap[getFullMethodName(structName, methodName)] = newmethodAndInOutTypes(method, inTypes, outTypes)
+ }
+}
+
+// CallFunction
+// @description: 调用方法
+// parameter:
+// @requestObj: 客户端对象
+// return:
+// @responseObj: 请求对象
+func CallFunction(requestObj *webServer.RequestObject) (responseObj *webServer.ResponseObject) {
+ responseObj = webServer.GetInitResponseObj()
+
+ var methodAndInOutTypes *methodAndInOutTypes
+ var ok bool
+
+ // 根据传入的ModuleName和MethodName找到对应的方法对象
+ key := getFullMethodName(requestObj.ModuleName, requestObj.MethodName)
+ if methodAndInOutTypes, ok = methodMap[key]; !ok {
+ logUtilPlus.ErrorLog("找不到指定的方法:%s", key)
+ responseObj.SetResultStatus(resultStatus.NotSpecificMethod)
+ return
+ }
+
+ // 判断参数数量是否相同
+ inTypesLength := len(methodAndInOutTypes.InTypes)
+ paramLength := len(requestObj.Parameters)
+ if paramLength != inTypesLength {
+ logUtilPlus.ErrorLog("传入的参数数量不符,本地方法%s的参数数量:%d,传入的参数数量为:%d", key, inTypesLength, paramLength)
+ responseObj.SetResultStatus(resultStatus.ParamNotMatch)
+ return
+ }
+
+ // 构造参数
+ in := make([]reflect.Value, inTypesLength)
+ for i := 0; i < inTypesLength; i++ {
+ inTypeItem := methodAndInOutTypes.InTypes[i]
+ paramItem := requestObj.Parameters[i]
+
+ // 已支持类型:Client,Player(非基本类型)
+ // 已支持类型:Bool,Int,Int8,Int16,Int32,Int64,Uint,Uint8,Uint16,Uint32,Uint64,Float32,Float64,String
+ // 已支持类型:以及上面所列出类型的Slice类型
+ // 未支持类型:Uintptr,Complex64,Complex128,Array,Chan,Func,Interface,Map,Ptr,Struct,UnsafePointer
+ // 由于byte与int8同义,rune与int32同义,所以并不需要单独处理
+ // 枚举参数的类型,并进行类型转换
+ switch inTypeItem.Kind() {
+ case reflect.Bool:
+ if param_bool, ok := paramItem.(bool); ok {
+ in[i] = reflect.ValueOf(param_bool)
+ }
+ case reflect.Int:
+ if param_float64, ok := paramItem.(int); ok {
+ in[i] = reflect.ValueOf(int(param_float64))
+ }
+ case reflect.Int8:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(int8(param_float64))
+ }
+ case reflect.Int16:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(int16(param_float64))
+ }
+ case reflect.Int32:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(int32(param_float64))
+ }
+ case reflect.Int64:
+ if param_float64, ok := paramItem.(int64); ok {
+ in[i] = reflect.ValueOf(int64(param_float64))
+ } else if param_uint64, ok := paramItem.(uint64); ok {
+ in[i] = reflect.ValueOf(int64(param_uint64))
+ } else if param_string, ok := paramItem.(string); ok {
+
+ i64, err := strconv.ParseInt(param_string, 10, 64)
+
+ if err == nil {
+ in[i] = reflect.ValueOf(i64)
+ }
+ }
+ case reflect.Uint:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(uint(param_float64))
+ }
+ case reflect.Uint8:
+ if param_float64, ok := paramItem.(uint8); ok {
+ in[i] = reflect.ValueOf(uint8(param_float64))
+ }
+ case reflect.Uint16:
+ if param_float64, ok := paramItem.(uint16); ok {
+ in[i] = reflect.ValueOf(uint16(param_float64))
+ }
+ case reflect.Uint32:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(uint32(param_float64))
+ }
+ case reflect.Uint64:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(uint64(param_float64))
+ }
+ case reflect.Float32:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(float32(param_float64))
+ }
+ case reflect.Float64:
+ if param_float64, ok := paramItem.(float64); ok {
+ in[i] = reflect.ValueOf(param_float64)
+ }
+ case reflect.String:
+ if param_string, ok := paramItem.(string); ok {
+ in[i] = reflect.ValueOf(param_string)
+ }
+ case reflect.Slice:
+ // 如果是Slice类型,则需要对其中的项再次进行类型判断及类型转换
+ if param_interface, ok := paramItem.([]interface{}); ok {
+ switch inTypeItem.String() {
+ case "[]bool":
+ params_inner := make([]bool, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_bool, ok := param_interface[i].(bool); ok {
+ params_inner[i] = param_bool
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]int":
+ params_inner := make([]int, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(int); ok {
+ params_inner[i] = int(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]int8":
+ params_inner := make([]int8, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(float64); ok {
+ params_inner[i] = int8(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]int16":
+ params_inner := make([]int16, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(float64); ok {
+ params_inner[i] = int16(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]int32":
+ params_inner := make([]int32, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ param_float64, ok := param_interface[i].(int32)
+ if ok {
+ params_inner[i] = int32(param_float64)
+ continue
+ } else {
+ param_int16, right := param_interface[i].(uint16)
+ if right == true {
+ params_inner[i] = int32(param_int16)
+ }
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]int64":
+ params_inner := make([]int64, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(int64); ok {
+ params_inner[i] = int64(param_float64)
+ } else if param_uint64, ok := param_interface[i].(uint64); ok {
+ params_inner[i] = int64(param_uint64)
+ } else if param_string, ok := param_interface[i].(string); ok {
+
+ i64, err := strconv.ParseInt(param_string, 10, 64)
+
+ if err == nil {
+ params_inner[i] = i64
+ }
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]uint":
+ params_inner := make([]uint, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(uint); ok {
+ params_inner[i] = uint(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ // case "[]uint8": 特殊处理
+ case "[]uint16":
+ params_inner := make([]uint16, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(uint16); ok {
+ params_inner[i] = uint16(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]uint32":
+ params_inner := make([]uint32, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(uint32); ok {
+ params_inner[i] = uint32(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]uint64":
+ params_inner := make([]uint64, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(uint64); ok {
+ params_inner[i] = uint64(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]float32":
+ params_inner := make([]float32, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(float64); ok {
+ params_inner[i] = float32(param_float64)
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]float64":
+ params_inner := make([]float64, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_float64, ok := param_interface[i].(float64); ok {
+ params_inner[i] = param_float64
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ case "[]string":
+ params_inner := make([]string, len(param_interface), len(param_interface))
+ for i := 0; i < len(param_interface); i++ {
+ if param_string, ok := param_interface[i].(string); ok {
+ params_inner[i] = param_string
+ }
+ }
+ in[i] = reflect.ValueOf(params_inner)
+ }
+ } else if inTypeItem.String() == "[]uint8" { // 由于[]uint8在传输过程中会被转化成字符串,所以单独处理;
+ if param_string, ok := paramItem.(string); ok {
+ param_uint8 := ([]uint8)(param_string)
+ in[i] = reflect.ValueOf(param_uint8)
+ }
+ }
+ }
+ }
+
+ // 判断是否有无效的参数(传入的参数类型和方法定义的类型不匹配导致没有赋值)
+ for _, item := range in {
+ if reflect.Value.IsValid(item) == false {
+ logUtilPlus.ErrorLog("type:%v,value:%v.方法%s传入的参数%v无效", reflect.TypeOf(item), reflect.ValueOf(item), key, requestObj.Parameters)
+ responseObj.SetResultStatus(resultStatus.ParamInValid)
+ return
+ }
+ }
+
+ // 传入参数,调用方法
+ if config.DEBUG {
+ if requestObj.MethodName != "GetRefreshData" {
+ logUtilPlus.DebugLog("Begin Call Func:module:%v, method:%v,inParams:%v\n\n", requestObj.ModuleName, requestObj.MethodName, in)
+ }
+ }
+
+ out := methodAndInOutTypes.Method.Call(in)
+
+ if config.DEBUG {
+ if requestObj.MethodName != "GetRefreshData" {
+ for i, v := range in {
+ logUtilPlus.DebugLog("\nparams %v,%v\n", i, v)
+ }
+ }
+ }
+
+ // 并输出结果到客户端(由于只有一个返回值,所以取out[0])
+ if responseObj, ok = (&out[0]).Interface().(*webServer.ResponseObject); !ok {
+ logUtilPlus.ErrorLog("返回值类型推断为ResponseObject 出错, tyep is :%v", reflect.TypeOf(out[0]))
+ responseObj.SetResultStatus(resultStatus.ParamInValid)
+ return
+ }
+ if config.DEBUG {
+ if requestObj.MethodName != "GetRefreshData" {
+ logUtilPlus.DebugLog("返回数据:code:%v, data:%v, mess:%v\n\n", responseObj.Code, responseObj.Value, responseObj.Message)
+ }
+ }
+ return
+}
diff --git a/.svn/pristine/59/59761351ace94d6dc0a08b6752112ec23c9e90ea.svn-base b/.svn/pristine/59/59761351ace94d6dc0a08b6752112ec23c9e90ea.svn-base
new file mode 100644
index 0000000..d54c4b9
--- /dev/null
+++ b/.svn/pristine/59/59761351ace94d6dc0a08b6752112ec23c9e90ea.svn-base
@@ -0,0 +1,82 @@
+/*
+ 此包提供通用的HTTP/HTTPS服务器功能;
+ 使用方法如下:
+ 1、初始化一个HttpServer/HttpsServer
+ server := NewHttpServer(addr string, isCheckIP bool)
+ 或
+ server := NewHttpsServer(addr, certFileName, keyFileName string, isCheckIP bool)
+ 其中参数说明如下:
+ addr:服务器监听地址
+ isCheckIP:是否需要验证客户端IP(此设置针对所有的请求,对于每个请求也可以单独设置;以此设置为优先)
+ certFileName:证书文件的路径
+ keyFileName:密钥文件的路径
+
+ 2、设置server的属性
+ 在服务器运行过程中,会有一些默认的行为,如果想要改变默认行为,可以通过调用以下的方法进行设置
+
+ 1)、设定Http Header信息
+ SetHeader(header map[string]string)
+ 默认的Http Header为空;如果设定了Http Header,则在每次请求时,都会给ResponseWriter加上该header属性
+ 2)、设定HTTP请求方法
+ SetMethod(method string)
+ 默认情况下,对请求的方法没有任何限制;如果设定了Method,则只允许该Method访问
+ 3)、设定当HTTP请求方法无效时,调用的处理器
+ SetInvalidMethodHandler(handler func(*Context))
+ 默认情况下,如果请求方法与所设置的方法不一致时,会返回406错误;如果设置了此属性,则会调用此属性进行处理
+ 4)、设定默认页的处理器
+ SetDefaultPageHandler(handler func(*Context))
+ 默认页指的是/, /favicon.ico这两个页面;默认情况下,仅仅是输出Welcome to home page.;如果需要针对做一些处理,可以设置此属性
+ 5)、设定未找到指定的回调时的处理器
+ SetNotFoundPageHandler(handler func(*Context))
+ 当服务器找不到对应的地址的Handler时,会返回404错误。如果需要处理一些非固定的地址时,可以使用此方法;比如回调地址中包含AppId,所以导致地址可变
+ 6)、设定在Debug模式下是否需要验证IP地址
+ SetIfCheckIPWhenDebug(value bool)
+ 默认情况下,在DEBUG模式时不验证IP;可以通过此属性改变此此行为
+ 7)、设定当IP无效时调用的处理器
+ SetIPInvalidHandler(handler func(*Context))
+ 当需要验证IP并且IP无效时,默认情况下会返回401错误;如果设定了此属性,则可以改变该行为
+ 8)、设定当检测到参数无效时调用的处理器
+ SetParamInvalidHandler(handler func(*Context))
+ 当检测到参数无效时,默认情况下会返回500错误;如果设置了此属性,则可以改变该行为
+ 9)、设定处理请求数据的处理器(例如压缩、解密等)
+ SetRequestDataHandler(handler func(*Context, []byte) ([]byte, error))
+ 如果设定此属性,则在处理接收到的请求数据时,会调用此属性
+ 10)、设定处理响应数据的处理器(例如压缩、加密等)
+ SetResponseDataHandler(handler func(*Context, []byte) ([]byte, error))
+ 如果设定此属性,则在处理返回给客户端的数据时,会调用此属性
+ 11)、设定请求执行时间的处理器
+ SetExecuteTimeHandler(handler func(*Context))
+ 如果在请求结束后想要处理调用的时间,则需要设置此属性;例如请求时间过长则记录日志等
+
+ 3、注册handler
+ server.RegisterHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
+ 参数如下:
+ // path:注册的访问路径
+ // callback:回调方法
+ // configObj:Handler配置对象
+ 例如:server.RegisterHandler("/get/notice", getNoticeConfig, &webServer.HandlerConfig{IsCheckIP: false, ParamNameList: []string{"appid"}})
+
+ 4、启动对应的服务器
+ server.Start(wg *sync.WaitGroup)
+
+ 5、context中提供了很多实用的方法
+ 1)、GetRequestPath() string:获取请求路径(该路径不带参数)
+ 2)、GetRequestIP() string:获取请求的客户端的IP地址
+ 3)、GetExecuteSeconds() int64:获取请求执行的秒数。当然也可以通过获取StartTime, EndTime属性自己进行更高精度的处理
+ 4)、String() string:将context里面的内容进行格式化,主要用于记录日志
+ 5)、FormValue(key string) string:获取请求的参数值(包括GET/POST/PUT/DELETE等所有参数)
+ 6)、PostFormValue(key string) string:获取POST的参数值
+ 7)、GetFormValueData() typeUtil.MapData:获取所有参数的MapData类型(包括GET/POST/PUT/DELETE等所有参数)
+ 8)、GetPostFormValueData() typeUtil.MapData:获取POST参数的MapData类型
+ 9)、GetMultipartFormValueData() typeUtil.MapData:获取MultipartForm的MapData类型
+ 10)、GetRequestBytes() (result []byte, exists bool, err error):获取请求字节数据
+ 11)、GetRequestString() (result string, exists bool, err error):获取请求字符串数据
+ 12)、Unmarshal(obj interface{}) (exists bool, err error):反序列化为对象(JSON)
+ 13)、WriteString(result string):输出字符串给客户端
+ 14)、WriteJson(result interface{}):输出json数据给客户端
+ 15)、RedirectTo(url string):重定向到其它页面
+ 如果以上的方法不能满足需求,则可以调用以下的方法来获取原始的Request/ResponseWriter对象进行处理
+ 16)、GetRequest() *http.Request:获取请求对象
+ 17)、GetResponseWriter() http.ResponseWriter:获取响应对象
+*/
+package webServer
diff --git a/.svn/pristine/59/59b53e67e3409c1fc1075865f0d23cd455d28d1f.svn-base b/.svn/pristine/59/59b53e67e3409c1fc1075865f0d23cd455d28d1f.svn-base
new file mode 100644
index 0000000..fdd8647
--- /dev/null
+++ b/.svn/pristine/59/59b53e67e3409c1fc1075865f0d23cd455d28d1f.svn-base
@@ -0,0 +1,184 @@
+package managecenterModel
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+ "time"
+
+ "goutil/stringUtil"
+)
+
+// 服务器组
+type ServerGroup struct {
+ // 服务器组Id
+ Id int32 `json:"GroupID"`
+
+ // 服务器组名称
+ Name string `json:"GroupName"`
+
+ // 服务器组Url
+ Url string `json:"GroupUrl"`
+
+ // 聊天服务器Url
+ ChatServerUrl string `json:"ChatServerUrl"`
+
+ // 数据库连接配置
+ DBConnectionConfig string `json:"DBConnectionConfig"`
+
+ // 服务器组状态(1:正常;2:维护)
+ GroupState int32 `json:"GroupState"`
+
+ // 服务器组热度(1:正常;2:新服;3:推荐)
+ GroupHeat int32 `json:"GroupHeat"`
+
+ // 服务器组负载(1:正常;2:火爆)
+ GroupLoad int32 `json:"GroupLoad"`
+
+ // 服务器开服时间对应的Unix时间戳
+ OpenTimeTick int64 `json:OpenTimeTick`
+
+ // 服务器组Ip(外网IP;内网IP;回调GS内网端口)
+ Ip string `json:"GroupIp"`
+
+ // 正式服或测试服;1:正式服;2:测试服
+ OfficialOrTest int32 `json:"OfficialOrTest"`
+
+ // 服务器组类型
+ Type int32 `json:"GroupType"`
+
+ // 服务器组排序
+ Order int32 `json:"GroupOrder"`
+
+ // 服务器组维护开始时间对应的时间戳
+ MaintainBeginTimeTick int64 `json:MaintainBeginTimeTick`
+
+ // 维护持续分钟数
+ MaintainMinutes int32 `json:"MaintainMinutes"`
+
+ // 维护信息
+ MaintainMessage string `json:"MaintainMessage"`
+
+ // 游戏监听地址
+ GameListenAddr string `json:"GameListenAddr"`
+
+ // 回调监听地址
+ CallbackListenAddr string `json:"CallbackListenAddr"`
+
+ // 外网回调地址
+ ExternalCallbackUrl string `json:"ExternalCallbackUrl"`
+
+ // 内网回调地址
+ InternalCallbackUrl string `json:"InternalCallbackUrl"`
+
+ // 是否在主群组(机房)内
+ IsInMainGroup bool `json:"IsInMainGroup"`
+
+ // 监控端口
+ GopsPort string `json:"GopsPort"`
+}
+
+// 排序方法(默认按照Id进行升序排序)
+// target:另一个服务器组对象
+// 是否是小于
+func (this *ServerGroup) SortByIdAsc(target *ServerGroup) bool {
+ return this.Id < target.Id
+}
+
+// 按照开服时间进行升序排序
+// target:另一个服务器组对象
+// 是否是小于
+func (this *ServerGroup) SortByOpenTimeAsc(target *ServerGroup) bool {
+ return this.OpenTimeTick < target.OpenTimeTick
+}
+
+// 获取数据库配置对象
+// 返回值:
+// 数据库配置对象
+// 错误对象
+func (this *ServerGroup) GetDBConfig() (*DBConnectionConfig, error) {
+ var dbConfig *DBConnectionConfig
+ if err := json.Unmarshal([]byte(this.DBConnectionConfig), &dbConfig); err != nil {
+ return nil, err
+ }
+
+ return dbConfig, nil
+}
+
+// 获取ip列表
+// 返回值:
+// ip列表
+func (this *ServerGroup) GetIPList() []string {
+ return stringUtil.Split(this.Ip, nil)
+}
+
+// 服务器组是否开启
+// 返回值:
+// 是否开启
+func (this *ServerGroup) IsOpen() bool {
+ return this.OpenTimeTick < time.Now().Unix()
+}
+
+// 获取游戏服务器的回调地址
+// suffix:地址后缀
+// 返回值
+// 游戏服务器的回调地址
+func (this *ServerGroup) GetGSCallbackUrl(suffix string) string {
+ // 如果是在主群组(机房)内,则使用内网地址,否则使用外网地址
+ url := ""
+ if this.IsInMainGroup {
+ url = this.InternalCallbackUrl
+ } else {
+ url = this.ExternalCallbackUrl
+ }
+
+ if url != "" {
+ if strings.HasSuffix(url, "/") {
+ return fmt.Sprintf("%s%s", url, suffix)
+ } else {
+ return fmt.Sprintf("%s/%s", url, suffix)
+ }
+ }
+
+ // 兼容旧的ManageCenter版本
+ ipList := this.GetIPList()
+
+ // 外网IP;内网IP;回调GS内网端口;如果数量小于3,则直接使用配置的GroupUrl;否则使用第3个值
+ if len(ipList) < 3 {
+ if strings.HasSuffix(this.Url, "/") {
+ return fmt.Sprintf("%s%s", this.Url, suffix)
+ } else {
+ return fmt.Sprintf("%s/%s", this.Url, suffix)
+ }
+ } else {
+ return fmt.Sprintf("http://%s:%s/%s", ipList[1], ipList[2], suffix)
+ }
+}
+
+// 判断服务器组是否相同
+// target:目标服务器组
+// 是否相同
+func (this *ServerGroup) IsEqual(target *ServerGroup) bool {
+ return this.Id == target.Id &&
+ this.Name == target.Name &&
+ this.Url == target.Url &&
+ this.ChatServerUrl == target.ChatServerUrl &&
+ this.DBConnectionConfig == target.DBConnectionConfig &&
+ this.GroupState == target.GroupState &&
+ this.GroupHeat == target.GroupHeat &&
+ this.GroupLoad == target.GroupLoad &&
+ this.OpenTimeTick == target.OpenTimeTick &&
+ this.Ip == target.Ip &&
+ this.OfficialOrTest == target.OfficialOrTest &&
+ this.Type == target.Type &&
+ this.Order == target.Order &&
+ this.MaintainBeginTimeTick == target.MaintainBeginTimeTick &&
+ this.MaintainMinutes == target.MaintainMinutes &&
+ this.MaintainMessage == target.MaintainMessage &&
+ this.GameListenAddr == target.GameListenAddr &&
+ this.CallbackListenAddr == target.CallbackListenAddr &&
+ this.ExternalCallbackUrl == target.ExternalCallbackUrl &&
+ this.InternalCallbackUrl == target.InternalCallbackUrl &&
+ this.IsInMainGroup == target.IsInMainGroup &&
+ this.GopsPort == target.GopsPort
+}
diff --git a/.svn/pristine/59/59bf7d0767b223adba34dffed1cabbbbbcb8210a.svn-base b/.svn/pristine/59/59bf7d0767b223adba34dffed1cabbbbbcb8210a.svn-base
new file mode 100644
index 0000000..d868a9d
--- /dev/null
+++ b/.svn/pristine/59/59bf7d0767b223adba34dffed1cabbbbbcb8210a.svn-base
@@ -0,0 +1,13 @@
+package model
+
+// 错误信息对象
+type ErrorInfo struct {
+ // 错误码
+ Code int `json:"code"`
+
+ // 错误提示信息
+ Message string `json:"message"`
+
+ // 对应删除失败的消息句柄
+ ReceiptHandle string `json:"receiptHandle"`
+}
diff --git a/.svn/pristine/5a/5a189554277f63f045f0d9feff1a77292f1eada0.svn-base b/.svn/pristine/5a/5a189554277f63f045f0d9feff1a77292f1eada0.svn-base
new file mode 100644
index 0000000..dc864a9
--- /dev/null
+++ b/.svn/pristine/5a/5a189554277f63f045f0d9feff1a77292f1eada0.svn-base
@@ -0,0 +1,93 @@
+package ipMgr
+
+import (
+ "encoding/json"
+ "fmt"
+ "time"
+
+ "goutil/securityUtil"
+ "goutil/webUtil"
+)
+
+var (
+ IP_SERVICE_URL = "http://ipip.7qule.com/query"
+)
+
+// 服务器的响应对象
+type QueryResponse struct {
+ // 响应结果的状态值
+ ResultStatus string
+
+ // 响应结果的数据
+ Data *IPInfo
+}
+
+// IP信息对象
+type IPInfo struct {
+ // 所属大陆块
+ Continent string
+
+ // 国家
+ Country string
+
+ // 省份
+ Region string
+
+ // 城市
+ City string
+
+ // 网络服务提供商
+ Isp string
+}
+
+// 查询ip地址的详细信息
+// appId: 为应用分配的唯一标识
+// appSecret: 为应用分配的密钥
+// ip: 待查询的ip地址
+// isDomestic: 是否为国内的IP
+// timeout:超时时间(单位:秒)
+// 返回值:
+// ipInfoObj: IP地址信息对象
+// err: 错误对象
+func Query(appId, appSecret, ip string, isDomestic bool, timeout int) (ipInfoObj *IPInfo, err error) {
+ timeStamp := fmt.Sprintf("%d", time.Now().Unix())
+ rawString := fmt.Sprintf("AppId=%s&IP=%s&Timestamp=%s&AppSecret=%s", appId, ip, timeStamp, appSecret)
+ sign := securityUtil.Md5String(rawString, true)
+
+ postData := make(map[string]string, 5)
+ postData["AppId"] = appId
+ postData["IP"] = ip
+ postData["IsDomestic"] = fmt.Sprintf("%t", isDomestic)
+ postData["Timestamp"] = timeStamp
+ postData["Sign"] = sign
+
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, timeout)
+
+ statusCode, result, err := webUtil.PostMapData(IP_SERVICE_URL, postData, header, transport)
+ //statusCode, result, err := webUtil.PostMapData(IP_SERVICE_URL, postData, header, transport)
+ if err != nil {
+ return
+ }
+ if statusCode != 200 {
+ err = fmt.Errorf("StatusCode:%d is wrong.", statusCode)
+ return
+ }
+
+ var queryResponseObj *QueryResponse
+ err = json.Unmarshal(result, &queryResponseObj)
+ if err != nil {
+ return
+ }
+
+ if queryResponseObj.ResultStatus != "" {
+ err = fmt.Errorf("Query result:%s", queryResponseObj.ResultStatus)
+ return
+ }
+
+ ipInfoObj = queryResponseObj.Data
+
+ return
+}
diff --git a/.svn/pristine/5a/5aaba2322ee53e31116a0cc59afcda10b566881f.svn-base b/.svn/pristine/5a/5aaba2322ee53e31116a0cc59afcda10b566881f.svn-base
new file mode 100644
index 0000000..4931c7e
--- /dev/null
+++ b/.svn/pristine/5a/5aaba2322ee53e31116a0cc59afcda10b566881f.svn-base
@@ -0,0 +1,27 @@
+package syncUtil
+
+import (
+ "fmt"
+ "testing"
+)
+
+var (
+ rwLockerUtilObj = NewRWLockerUtil()
+)
+
+func RWLockerUtil_TestGetLock(t *testing.T) {
+ count := 100
+ for i := 1; i <= count; i++ {
+ rwLockerUtilObj.GetLock(fmt.Sprintf("%d", i))
+ if lockerCount := len(rwLockerUtilObj.lockerMap); lockerCount != i {
+ t.Errorf("(GetLock)Expected %d locker, but now got: %d", count, lockerCount)
+ }
+ }
+
+ for i := count; i > 0; i-- {
+ rwLockerUtilObj.ReleaseLock(fmt.Sprintf("%d", i))
+ if lockerCount := len(rwLockerUtilObj.lockerMap); lockerCount != i-1 {
+ t.Errorf("(ReleaseLock)Expected %d locker, but now got: %d", count, lockerCount)
+ }
+ }
+}
diff --git a/.svn/pristine/5b/5b1d2eb77b85e4e36232243c7273ed32a23df5dc.svn-base b/.svn/pristine/5b/5b1d2eb77b85e4e36232243c7273ed32a23df5dc.svn-base
new file mode 100644
index 0000000..57f1cf1
--- /dev/null
+++ b/.svn/pristine/5b/5b1d2eb77b85e4e36232243c7273ed32a23df5dc.svn-base
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "associatedIndex": 4
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ file://$PROJECT_DIR$/common/configs/init.go
+ 34
+
+
+
+ file://$PROJECT_DIR$/common/httpServer/reflect.go
+ 362
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.svn/pristine/5b/5b7144648d38e77bea09228526e4a1cc66a86fd9.svn-base b/.svn/pristine/5b/5b7144648d38e77bea09228526e4a1cc66a86fd9.svn-base
new file mode 100644
index 0000000..a953b31
--- /dev/null
+++ b/.svn/pristine/5b/5b7144648d38e77bea09228526e4a1cc66a86fd9.svn-base
@@ -0,0 +1,175 @@
+package managecenterMgr
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+
+ "Framework/managecenterModel"
+ . "Framework/managecenterModel"
+ "goutil/logUtil"
+ "goutil/webUtil"
+)
+
+var (
+ serverMap = make(map[int32]map[int32]*Server, 128)
+ serverDistinctMap = make(map[int32]*Server, 1024)
+ serverHash string
+)
+
+// 重新加载服务器
+func reloadServer(isInit bool) error {
+ //logUtil.DebugLog("开始刷新服务器列表")
+
+ url := getManageCenterUrl("/API/ServerList.ashx")
+
+ // 定义请求参数
+ postDict := make(map[string]string)
+ postDict["GroupType"] = "Mix"
+ postDict["HashValue"] = serverHash
+
+ //请求url,请求头
+ header := webUtil.GetFormHeader()
+ transport := webUtil.NewTransport()
+ transport.DisableKeepAlives = true
+ transport = webUtil.GetTimeoutTransport(transport, 30)
+
+ statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, transport)
+ //statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, nil)
+ if err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器列表出错,url:%s,错误信息为:%s", url, err))
+ return err
+ }
+ if statusCode != 200 {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器列表出错,url:%s,错误码为:%d", url, statusCode))
+ return err
+ }
+
+ // 解析返回值
+ returnObj := new(ReturnObject)
+ if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器列表出错,反序列化返回值出错,错误信息为:%s, str:%s", err, string(returnBytes)))
+ return err
+ }
+
+ // 判断返回状态是否成功
+ if returnObj.Code != 0 {
+ // 数据没有变化,所以没有获取到新的数据,不能算错误。
+ if returnObj.Code == 47 || returnObj.Message == "DataNotChanged" {
+ //如果本地集合为空,且数据又没变化时,重新初始化一下本地hash值
+ if len(serverMap) == 0 {
+ serverHash = ""
+ }
+ return nil
+ } else {
+ msg := fmt.Sprintf("获取服务器列表出错,返回状态:%d,信息为:%s", returnObj.Code, returnObj.Message)
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ }
+ }
+
+ // 解析Data
+ tmpServerList := make([]*Server, 0, 1024)
+ if data, ok := returnObj.Data.(string); !ok {
+ msg := "获取服务器列表出错,返回的数据不是string类型"
+ logUtil.ErrorLog(msg)
+ return errors.New(msg)
+ } else {
+ if err = json.Unmarshal([]byte(data), &tmpServerList); err != nil {
+ logUtil.ErrorLog(fmt.Sprintf("获取服务器列表出错,反序列化数据出错,错误信息为:%s", err))
+ return err
+ }
+ }
+
+ //logUtil.DebugLog(fmt.Sprintf("刷新服务器信息结束,服务器数量:%d", len(tmpServerList)))
+
+ tmpServerMap := make(map[int32]map[int32]*Server, 128)
+ tmpServerDistinctMap := make(map[int32]*Server, 1024)
+ for _, item := range tmpServerList {
+ // 构造tmpServerMap数据
+ if _, ok := tmpServerMap[item.PartnerId]; !ok {
+ tmpServerMap[item.PartnerId] = make(map[int32]*Server, 1024)
+ }
+ tmpServerMap[item.PartnerId][item.Id] = item
+
+ // 构造tmpServerDistinctMap数据
+ tmpServerDistinctMap[item.Id] = item
+ }
+
+ // 赋值给最终的serverMap、serverDistinctMap
+ serverMap = tmpServerMap
+ serverDistinctMap = tmpServerDistinctMap
+ serverHash = returnObj.HashValue
+
+ //通知变更
+ mcDataChangeCallBack(managecenterModel.ServerData, isInit)
+
+ return nil
+}
+
+// 根据服务器组Id获取对应的服务器列表
+// serverGroupId:服务器组Id
+// 返回值:
+// 服务器列表
+func GetServerListByGroupId(serverGroupId int32) (serverList []*Server) {
+ for _, subServerMap := range serverMap {
+ for _, item := range subServerMap {
+ if item.GroupId == serverGroupId {
+ serverList = append(serverList, item)
+ }
+ }
+ }
+
+ return
+}
+
+// 根据合作商Id获取对应的服务器列表
+// partnerId:合作商Id
+// 返回值:
+// 服务器列表
+func GetServerListByPartnerId(partnerId int32) (serverList []*Server) {
+ for _, item := range serverMap[partnerId] {
+ serverList = append(serverList, item)
+ }
+
+ return
+}
+
+// 根据合作商对象、服务器Id获取服务器对象
+// partnerObj:合作商对象
+// serverId:服务器Id
+// 返回值:
+// 服务器对象
+// 是否存在
+func GetServer(partnerObj *Partner, serverId int32) (serverObj *Server, exist bool) {
+ if subServerMap, exist1 := serverMap[partnerObj.Id]; exist1 {
+ serverObj, exist = subServerMap[serverId]
+ }
+
+ return
+}
+
+// 根据合作商Id、服务器Id获取服务器对象
+// partnerId:合作商Id
+// serverId:服务器Id
+// 返回值:
+// 服务器对象
+// 是否存在
+func GetServerItem(partnerId, serverId int32) (serverObj *Server, exist bool) {
+ if subServerMap, exist1 := serverMap[partnerId]; exist1 {
+ serverObj, exist = subServerMap[serverId]
+ }
+
+ return
+}
+
+// 获取不重复的服务器Id列表
+// 返回值:
+// 不重复的服务器Id列表
+func GetDistinctServerIdList() (distinctServerIdList []int32) {
+ for _, item := range serverDistinctMap {
+ distinctServerIdList = append(distinctServerIdList, item.Id)
+ }
+
+ return
+}
diff --git a/.svn/pristine/5b/5ba8ba3ff47876b2475132ee02919a860a69a8d5.svn-base b/.svn/pristine/5b/5ba8ba3ff47876b2475132ee02919a860a69a8d5.svn-base
new file mode 100644
index 0000000..039612a
--- /dev/null
+++ b/.svn/pristine/5b/5ba8ba3ff47876b2475132ee02919a860a69a8d5.svn-base
@@ -0,0 +1,19 @@
+package monitorMgr
+
+import (
+ "testing"
+)
+
+func TestDuplicate(t *testing.T) {
+ SetParam("20.255.0.7", "Test", 5)
+
+ content := "content"
+
+ if isDuplicate(content) == true {
+ t.Errorf("%s不应该重复却重复了", content)
+ }
+ addToMap(content)
+ if isDuplicate(content) == false {
+ t.Errorf("%s应该重复却没有重复", content)
+ }
+}
diff --git a/.svn/pristine/5b/5bae2a2351dc932639f48484b5f38da44c769cab.svn-base b/.svn/pristine/5b/5bae2a2351dc932639f48484b5f38da44c769cab.svn-base
new file mode 100644
index 0000000..d582285
--- /dev/null
+++ b/.svn/pristine/5b/5bae2a2351dc932639f48484b5f38da44c769cab.svn-base
@@ -0,0 +1,70 @@
+package webServer
+
+import (
+ "fmt"
+ "net/http"
+ "sync"
+
+ "goutil/logUtil"
+)
+
+// Https服务器对象
+type HttpsServer struct {
+ addr string
+ certFileName string
+ keyFileName string
+ IWebServer
+ server http.Server
+}
+
+func (this *HttpsServer) SetAddr(addr string) {
+ this.addr = addr
+ this.server.Addr = addr
+}
+
+// 启动HttpsServer
+func (this *HttpsServer) Start(wg *sync.WaitGroup) {
+ defer func() {
+ wg.Done()
+ }()
+
+ // 开启监听
+ msg := fmt.Sprintf("http server begins to listen on: %s...", this.addr)
+ fmt.Println(msg)
+ logUtil.InfoLog(msg)
+
+ if err := this.server.ListenAndServeTLS(this.certFileName, this.keyFileName); err != nil {
+ panic(fmt.Sprintf("https server ListenAndServeTLS Error:%v", err))
+ }
+}
+
+// 创建新的HttpsServer
+// isCheckIP:该属性已丢弃,可以任意赋值
+func NewHttpsServer(addr, certFileName, keyFileName string, isCheckIP bool) *HttpsServer {
+ webServerObj := NewWebServer(isCheckIP)
+
+ return &HttpsServer{
+ addr: addr,
+ certFileName: certFileName,
+ keyFileName: keyFileName,
+ IWebServer: webServerObj,
+ server: http.Server{
+ Addr: addr,
+ Handler: webServerObj,
+ },
+ }
+}
+
+// 创建新的HttpsServer
+func NewHttpsServer2(addr, certFileName, keyFileName string, webServerObj IWebServer) *HttpsServer {
+ return &HttpsServer{
+ addr: addr,
+ certFileName: certFileName,
+ keyFileName: keyFileName,
+ IWebServer: webServerObj,
+ server: http.Server{
+ Addr: addr,
+ Handler: webServerObj,
+ },
+ }
+}
diff --git a/.svn/pristine/5b/5be359c1bf55a499ca0575b8b4af358bbfbb7565.svn-base b/.svn/pristine/5b/5be359c1bf55a499ca0575b8b4af358bbfbb7565.svn-base
new file mode 100644
index 0000000..271273f
--- /dev/null
+++ b/.svn/pristine/5b/5be359c1bf55a499ca0575b8b4af358bbfbb7565.svn-base
@@ -0,0 +1,131 @@
+package deviceUtil
+
+import (
+ "testing"
+)
+
+func TestConvertMacToStarndardFormat(t *testing.T) {
+ mac := ""
+ expected := ""
+ got := ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "00:00:00:00:00:00"
+ expected = ""
+ got = ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "02:00:00:00:00:00"
+ expected = ""
+ got = ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "02:00:00:00:00"
+ expected = ""
+ got = ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "020000000020"
+ expected = "02:00:00:00:00:20"
+ got = ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "02:00:00:00:00:20"
+ expected = "02:00:00:00:00:20"
+ got = ConvertMacToStandardFormat(mac)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+}
+
+func TestConvertIdfaToStandardFormat(t *testing.T) {
+ idfa := ""
+ expected := ""
+ got := ConvertIdfaToStandardFormat(idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ idfa = "00000000-0000-0000-0000-000000000000"
+ expected = ""
+ got = ConvertIdfaToStandardFormat(idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ idfa = "00000000-0000-0000-0000-000000000000-123"
+ expected = "00000000-0000-0000-0000-000000000000-123"
+ got = ConvertIdfaToStandardFormat(idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ idfa = "00000000-1234-5678-0000-000000000000"
+ expected = "00000000-1234-5678-0000-000000000000"
+ got = ConvertIdfaToStandardFormat(idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ idfa = "00000000123456780000000000000000"
+ expected = "00000000-1234-5678-0000-000000000000"
+ got = ConvertIdfaToStandardFormat(idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+}
+
+func TestGetIdentifier(t *testing.T) {
+ mac := ""
+ idfa := ""
+ expected := ""
+ got := GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "00:00:00:00:00:00"
+ expected = ""
+ got = GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "02:00:00:00:00:00"
+ expected = ""
+ got = GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "020000000020"
+ expected = "02:00:00:00:00:20"
+ got = GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ mac = "02:00:00:00:00:20"
+ expected = "02:00:00:00:00:20"
+ got = GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+
+ idfa = "00000000123456780000000000000000"
+ expected = "00000000-1234-5678-0000-000000000000"
+ got = GetIdentifier(mac, idfa)
+ if got != expected {
+ t.Errorf("Expected: %s, but got:%s", expected, got)
+ }
+}
diff --git a/.svn/pristine/5c/5ce606a1bf41c73ac8d2169614eb70b18e7551ae.svn-base b/.svn/pristine/5c/5ce606a1bf41c73ac8d2169614eb70b18e7551ae.svn-base
new file mode 100644
index 0000000..a31c5dc
--- /dev/null
+++ b/.svn/pristine/5c/5ce606a1bf41c73ac8d2169614eb70b18e7551ae.svn-base
@@ -0,0 +1,56 @@
+package mysqlUtil
+
+import (
+ "fmt"
+ "testing"
+ "time"
+)
+
+func TestOpenMysqlConnection(t *testing.T) {
+ connectionString := "root:moqikaka3306@tcp(10.1.0.10:3306)/gameserver_data?charset=utf8&parseTime=true&loc=Local&timeout=60s||MaxOpenConns=10||MaxIdleConns=5"
+
+ if _, err := OpenMysqlConnection(connectionString); err != nil {
+ t.Errorf("there should be no err, but now has:%s", err)
+ }
+}
+
+func TestOpenMysqlConnection2(t *testing.T) {
+ connectionString := "root:moqikaka3306@tcp(10.1.0.10:3306)/gameserver_data?charset=utf8&parseTime=true&loc=Local&timeout=60s"
+ maxOpenConns := 10
+ maxIdleConns := 5
+
+ if _, err := OpenMysqlConnection2(connectionString, maxOpenConns, maxIdleConns); err != nil {
+ t.Errorf("there should be no err, but now has:%s", err)
+ }
+}
+
+func TestOpenMysqlConnection3(t *testing.T) {
+ dbConfigObj := NewDBConfig("root:moqikaka3306@tcp(10.1.0.10:3306)/sdkcenter?charset=utf8&parseTime=true&loc=Local&timeout=10s", 5, 2)
+ if _, err := OpenMysqlConnection3(dbConfigObj); err != nil {
+ t.Errorf("there should be no err, but now has:%s", err)
+ }
+}
+
+func TestTestConnection(t *testing.T) {
+ dbConfigObj := NewDBConfig("root:moqikaka3306@tcp(10.1.0.10:3306)/sdkcenter?charset=utf8&parseTime=true&loc=Local&timeout=10s", 5, 2)
+ dbObj, err := OpenMysqlConnection3(dbConfigObj)
+ if err != nil {
+ t.Errorf("there should be no err, but now has:%s", err)
+ }
+
+ succeedCount := 0
+ expectedCount := 5
+ for i := 0; i < expectedCount; i++ {
+ if err := TestConnection(dbObj); err != nil {
+ fmt.Printf("%s:%s\n", time.Now(), err)
+ } else {
+ succeedCount += 1
+ fmt.Printf("%s:%s\n", time.Now(), "ok")
+ }
+ time.Sleep(time.Second * 3)
+ }
+
+ if succeedCount != expectedCount {
+ t.Errorf("ExecptedCount:%d, but got %d", expectedCount, succeedCount)
+ }
+}
diff --git a/.svn/pristine/5d/5dc12fc1c712eed283d8593d10c63d946be7337c.svn-base b/.svn/pristine/5d/5dc12fc1c712eed283d8593d10c63d946be7337c.svn-base
new file mode 100644
index 0000000..dcbbee5
--- /dev/null
+++ b/.svn/pristine/5d/5dc12fc1c712eed283d8593d10c63d946be7337c.svn-base
@@ -0,0 +1,218 @@
+package webServer
+
+import (
+ "encoding/json"
+ "fmt"
+ "goutil/jsonUtil"
+ "goutil/logUtilPlus"
+ "goutil/typeUtil"
+ "goutil/zlibUtil"
+ "io/ioutil"
+ "net/http"
+)
+
+// ApiContext
+// @description: Api请求上下文对象
+type ApiContext struct {
+ // 请求对象
+ request *http.Request
+
+ // 应答写对象
+ responseWriter http.ResponseWriter
+
+ // 请求数据
+ requestBytes []byte
+
+ // 字典形式的请求数据
+ requestDataByMap typeUtil.MapData
+
+ //获取头部信息
+ header *http.Header
+}
+
+// GetRequest
+// @description: 获取请求对象
+// parameter:
+// @receiver this: this
+// return:
+// @*http.Request: 请求对象
+func (this *ApiContext) GetRequest() *http.Request {
+ return this.request
+}
+
+// GetResponseWriter
+// @description: 获取应答写对象
+// parameter:
+// @receiver this: this
+// return:
+// @http.ResponseWriter: 应答写对象
+func (this *ApiContext) GetResponseWriter() http.ResponseWriter {
+ return this.responseWriter
+}
+
+// GetRequestBytes
+// @description: 获取请求字节数据
+// parameter:
+// @receiver this: this
+// return:
+// @[]byte: 请求字节数组
+func (this *ApiContext) GetRequestBytes() []byte {
+ return this.requestBytes
+}
+
+// readContent
+// @description: 读取内容
+// parameter:
+// @receiver this: this 请求对象
+// @isZlib: 是否数据压缩
+// return:
+// @content: 二进制格式的内容
+// @err: 错误对象
+func (this *ApiContext) readContent(isZlib bool) (content []byte, err error) {
+ var buffer []byte
+
+ defer this.request.Body.Close()
+ if buffer, err = ioutil.ReadAll(this.request.Body); err != nil {
+ logUtilPlus.ErrorLog(fmt.Sprintf("url:%s,读取数据出错,错误信息为:%s", this.request.RequestURI, err))
+ return
+ }
+
+ // 不压缩,则直接返回
+ if isZlib == false {
+ this.requestBytes = buffer
+
+ return buffer, err
+ }
+
+ // 解压数据
+ if content, err = zlibUtil.Decompress(buffer); err != nil {
+ logUtilPlus.ErrorLog(fmt.Sprintf("url:%s,解压缩数据出错,错误信息为:%s", this.request.RequestURI, err))
+ return
+ }
+
+ this.requestBytes = content
+
+ return
+}
+
+// Unmarshal
+// @description: 反序列化
+// parameter:
+// @receiver this: this
+// @obj: 反序列化结果数据
+// return:
+// @error: 反序列化错误数据
+func (this *ApiContext) Unmarshal(obj interface{}) error {
+ contentData := this.GetRequestBytes()
+
+ var errMsg error
+
+ // 反序列化
+ if obj, errMsg = json.Marshal(contentData); errMsg != nil {
+ logUtilPlus.ErrorLog(fmt.Sprintf("反序列化%s出错,错误信息为:%s", string(contentData), errMsg.Error()))
+ return errMsg
+ }
+
+ return nil
+}
+
+// RequestDataByMap
+// @description: 获取请求的map格式数据
+// parameter:
+// @receiver this: this
+// return:
+// @typeUtil.MapData: map数据
+// @error: 错误信息
+func (this *ApiContext) RequestDataByMap() (typeUtil.MapData, error) {
+ if this.requestDataByMap != nil {
+ return this.requestDataByMap, nil
+ }
+
+ var data typeUtil.MapData
+ if err := this.Unmarshal(&data); err != nil {
+ return nil, err
+ }
+
+ this.requestDataByMap = data
+
+ return this.requestDataByMap, nil
+}
+
+// RequestDataBySlice
+// @description: 获取请求的slice格式数据
+// parameter:
+// @receiver this: this
+// return:
+// @[]interface{}: 返回的数组数据
+func (this *ApiContext) RequestDataBySlice() []interface{} {
+ result := make([]interface{}, 0, 8)
+ for _, value := range this.requestDataByMap {
+ result = append(result, value)
+ }
+ return result
+}
+
+// RequestDataBySlice2
+// @description: 获取请求的slice格式数据
+// parameter:
+// @receiver this: this
+// return:
+// @[]interface{}: 返回的数组数据
+// @error:
+func (this *ApiContext) RequestDataBySlice2() (interface{}, error) {
+ contentData := this.GetRequestBytes()
+
+ // 反序列化
+ var result interface{}
+ var errMsg error
+ if result, errMsg = jsonUtil.UnMarshalWithNumberType(string(contentData)); errMsg != nil {
+ logUtilPlus.ErrorLog(fmt.Sprintf("用[]interface{}反序列化%s出错,错误信息为:%s", string(contentData), errMsg.Error()))
+ return nil, errMsg
+ }
+ return result, nil
+}
+
+// RequestDataBySlice2ByJson
+// @description: 获取请求的slice格式数据
+// parameter:
+// @receiver this: this
+// return:
+// @[]interface{}: 返回的数组数据
+// @error:
+func (this *ApiContext) RequestDataBySlice2ByJson() ([]interface{}, error) {
+ contentData := this.GetRequestBytes()
+
+ // 反序列化
+ result := make([]interface{}, 0, 8)
+ if errMsg := json.Unmarshal(contentData, &result); errMsg != nil {
+ logUtilPlus.ErrorLog(fmt.Sprintf("用[]interface{}反序列化%s出错,错误信息为:%s", string(contentData), errMsg.Error()))
+ return nil, errMsg
+ }
+
+ return result, nil
+}
+
+// NewApiContext
+// @description: 新建API上下文对象
+// parameter:
+// @_request: 请求对象
+// @_responseWriter: 应答写对象
+// @isZlib: 数据是否压缩
+// return:
+// @*ApiContext: 上下文
+// @error: 错误信息
+func NewApiContext(_request *http.Request, _responseWriter http.ResponseWriter, isZlib bool) (*ApiContext, error) {
+ context := &ApiContext{
+ request: _request,
+ header: &_request.Header,
+ responseWriter: _responseWriter,
+ }
+
+ // 读取数据
+ _, errMsg := context.readContent(isZlib)
+ if errMsg != nil {
+ return nil, errMsg
+ }
+
+ return context, nil
+}
diff --git a/.svn/pristine/5d/5dca3ad5e01acc3892a93342d49523e7afb43b05.svn-base b/.svn/pristine/5d/5dca3ad5e01acc3892a93342d49523e7afb43b05.svn-base
new file mode 100644
index 0000000..93eccef
--- /dev/null
+++ b/.svn/pristine/5d/5dca3ad5e01acc3892a93342d49523e7afb43b05.svn-base
@@ -0,0 +1,99 @@
+package securityUtil
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "errors"
+)
+
+var (
+ // ErrInvalidBlockSize indicates hash blocksize <= 0.
+ ErrInvalidBlockSize = errors.New("invalid blocksize")
+
+ // ErrInvalidPKCS7Data indicates bad input to PKCS7 pad or unpad.
+ ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)")
+
+ // ErrInvalidPKCS7Padding indicates PKCS7 unpad fails to bad input.
+ ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
+)
+
+// pkcs7Pad right-pads the given byte slice with 1 to n bytes, where
+// n is the block size. The size of the result is x times n, where x
+// is at least 1.
+func pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
+ if b == nil || len(b) == 0 {
+ return nil, ErrInvalidPKCS7Data
+ }
+ if blocksize <= 0 {
+ return nil, ErrInvalidBlockSize
+ }
+ n := blocksize - (len(b) % blocksize)
+ pb := make([]byte, len(b)+n)
+ copy(pb, b)
+ copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
+
+ return pb, nil
+}
+
+// pkcs7Unpad validates and unpads data from the given bytes slice.
+// The returned value will be 1 to n bytes smaller depending on the
+// amount of padding, where n is the block size.
+func pkcs7Unpad(b []byte, blocksize int) ([]byte, error) {
+ if b == nil || len(b) == 0 {
+ return nil, ErrInvalidPKCS7Data
+ }
+ if blocksize <= 0 {
+ return nil, ErrInvalidBlockSize
+ }
+ if len(b)%blocksize != 0 {
+ return nil, ErrInvalidPKCS7Padding
+ }
+
+ c := b[len(b)-1]
+ n := int(c)
+ if n == 0 || n > len(b) {
+ return nil, ErrInvalidPKCS7Padding
+ }
+
+ for i := 0; i < n; i++ {
+ if b[len(b)-n+i] != c {
+ return nil, ErrInvalidPKCS7Padding
+ }
+ }
+
+ return b[:len(b)-n], nil
+}
+
+func AESEncrypt_CBC_Pkcs7(src []byte, key []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ src, err = pkcs7Pad(src, block.BlockSize())
+ if err != nil {
+ return nil, err
+ }
+
+ blockmode := cipher.NewCBCEncrypter(block, key)
+ blockmode.CryptBlocks(src, src)
+
+ return src, nil
+}
+
+func AESDecrypt_CBC_Pkcs7(src []byte, key []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ blockmode := cipher.NewCBCDecrypter(block, key)
+ blockmode.CryptBlocks(src, src)
+ src, err = pkcs7Unpad(src, block.BlockSize())
+ if err != nil {
+ return nil, err
+ }
+
+ return src, nil
+}
diff --git a/.svn/pristine/5d/5df6cb671df6614fa95300a808373169e18b0950.svn-base b/.svn/pristine/5d/5df6cb671df6614fa95300a808373169e18b0950.svn-base
new file mode 100644
index 0000000..28587cd
--- /dev/null
+++ b/.svn/pristine/5d/5df6cb671df6614fa95300a808373169e18b0950.svn-base
@@ -0,0 +1,87 @@
+package httpServer
+
+import (
+ "common/webServer"
+ "net/http"
+
+ "common/resultStatus"
+)
+
+// 处理函数
+type HandleFunc func(context *ApiContext) *webServer.ResponseObject
+
+// ApiHandler
+// @description: API处理结构
+type ApiHandler struct {
+ // API完整路径名称
+ apiFullName string
+
+ // 方法定义
+ handleFun HandleFunc
+
+ // 方法参数名称集合
+ funcParamNames []string
+}
+
+// ApiFullName
+// @description: API完整路径名称
+// parameter:
+// @receiver this: this
+// return:
+// @string:
+func (this *ApiHandler) ApiFullName() string {
+ return this.apiFullName
+}
+
+// HandleFun
+// @description: 方法定义
+// parameter:
+// @receiver this: this
+// return:
+// @HandleFunc: 方法
+func (this *ApiHandler) HandleFun() HandleFunc {
+ return this.handleFun
+}
+
+// FuncParamNames
+// @description: 方法参数名称集合
+// parameter:
+// @receiver this: this
+// return:
+// @[]string: 方法参数名称集合
+func (this *ApiHandler) FuncParamNames() []string {
+ return this.funcParamNames
+}
+
+// CheckParam
+// @description: 检测参数数量
+// parameter:
+// @receiver this: this
+// @r:
+// return:
+// @resultStatus.ResultStatus: 状态码数据
+func (this *ApiHandler) CheckParam(r *http.Request) resultStatus.ResultStatus {
+ for _, name := range this.funcParamNames {
+ if r.Form[name] == nil || len(r.Form[name]) == 0 {
+ return resultStatus.APIParamError
+ }
+ }
+
+ return resultStatus.Success
+}
+
+// newApiHandler
+// @description: 创建新的请求方法对象
+// parameter:
+// @_apiFullName: API完整路径名称
+// @_funcDefinition: 方法定义
+// @_funcParamNames: 方法参数名称集合
+// return:
+// @*ApiHandler: 请求方法对象
+func newApiHandler(_apiFullName string, _funcDefinition HandleFunc, _funcParamNames ...string) *ApiHandler {
+ return &ApiHandler{
+ apiFullName: _apiFullName,
+ handleFun: _funcDefinition,
+ funcParamNames: _funcParamNames,
+ }
+}
diff --git a/.svn/pristine/5e/5e0f209f6e9be1f84238e9cb97288fda3cb63dd8.svn-base b/.svn/pristine/5e/5e0f209f6e9be1f84238e9cb97288fda3cb63dd8.svn-base
new file mode 100644
index 0000000..50e10d2
--- /dev/null
+++ b/.svn/pristine/5e/5e0f209f6e9be1f84238e9cb97288fda3cb63dd8.svn-base
@@ -0,0 +1,345 @@
+package xmlUtil
+
+import (
+ "bytes"
+ "container/list"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// A NodeType is the type of a Node.
+type NodeType uint
+
+const (
+ // 文档对象节点(根节点)
+ DocumentNode NodeType = iota
+
+ // 头不声明节点
+ DeclarationNode
+
+ // 元素节点
+ ElementNode
+
+ // 节点文本
+ TextNode
+
+ // 注释
+ CommentNode
+)
+
+// xml节点对象
+type Node struct {
+ Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
+
+ Type NodeType
+ NodeName string
+ Namespace string
+ Attr []xml.Attr
+
+ level int // node level in the tree
+}
+
+// InnerText returns the text between the start and end tags of the object.
+func (n *Node) InnerText() string {
+ if n.Type == TextNode || n.Type == CommentNode {
+ return n.NodeName
+ }
+
+ var buf bytes.Buffer
+ for child := n.FirstChild; child != nil; child = child.NextSibling {
+ // filt commentnode
+ if child.Type == CommentNode {
+ continue
+ }
+
+ buf.WriteString(child.InnerText())
+ }
+
+ return buf.String()
+}
+
+func outputXML(buf *bytes.Buffer, n *Node) {
+ if n.Type == TextNode || n.Type == CommentNode {
+ buf.WriteString(strings.TrimSpace(n.NodeName))
+ return
+ }
+ buf.WriteString("<" + n.NodeName)
+ for _, attr := range n.Attr {
+ if attr.Name.Space != "" {
+ buf.WriteString(fmt.Sprintf(` %s:%s="%s"`, attr.Name.Space, attr.Name.Local, attr.Value))
+ } else {
+ buf.WriteString(fmt.Sprintf(` %s="%s"`, attr.Name.Local, attr.Value))
+ }
+ }
+ buf.WriteString(">")
+ for child := n.FirstChild; child != nil; child = child.NextSibling {
+ outputXML(buf, child)
+ }
+ buf.WriteString(fmt.Sprintf("%s>", n.NodeName))
+}
+
+// OutputXML returns the text that including tags name.
+func (n *Node) OutputXML() string {
+ var buf bytes.Buffer
+ outputXML(&buf, n)
+ return buf.String()
+}
+
+// get all children
+func (n *Node) Children() []*Node {
+ childrenList := make([]*Node, 0)
+ nowChild := n.FirstChild
+ for {
+ if nowChild == nil {
+ break
+ }
+
+ childrenList = append(childrenList, nowChild)
+ if nowChild == n.LastChild {
+ break
+ }
+
+ nowChild = nowChild.NextSibling
+ }
+
+ return childrenList
+}
+
+// get children len
+func (n *Node) ChildrenLen() int {
+ var count int = 0
+ nowChild := n.FirstChild
+ for {
+ if nowChild == nil {
+ break
+ }
+
+ count += 1
+ if nowChild == n.LastChild {
+ break
+ }
+
+ nowChild = nowChild.NextSibling
+ }
+
+ return count
+}
+
+// get all attribute
+func (n *Node) ALLAttribute() []xml.Attr {
+ if n.Attr == nil {
+ return nil
+ }
+
+ return n.Attr[:]
+}
+
+// 获取属性个数
+func (n *Node) AttributeLen() int {
+ if n.Attr == nil {
+ return 0
+ }
+
+ return len(n.Attr)
+}
+
+// 输出所有(主要用于测试)
+func (this *Node) OutALL() {
+ stack := list.New()
+ tmpItem := this
+ for {
+ if tmpItem != nil {
+ stack.PushBack(tmpItem)
+ tmpItem = tmpItem.NextSibling
+ }
+
+ break
+ }
+
+ for {
+ if stack.Len() <= 0 {
+ break
+ }
+
+ nowNode := stack.Front().Value.(*Node)
+ stack.Remove(stack.Front())
+ for _, item := range nowNode.Children() {
+ stack.PushFront(item)
+ }
+
+ fmt.Println("name:", nowNode.NodeName, " level: ", nowNode.level, " attr:", nowNode.Attr)
+ }
+}
+
+// SelectElements finds child elements with the specified name.
+func (n *Node) SelectElements(name string) []*Node {
+ return Find(n, name)
+}
+
+// SelectElements finds child elements with the specified name.
+func (n *Node) SelectElement(name string) *Node {
+ return FindOne(n, name)
+}
+
+// SelectAttr returns the attribute value with the specified name.
+func (n *Node) SelectAttr(name string) (string, bool) {
+ var local, space string
+ local = name
+ if i := strings.Index(name, ":"); i > 0 {
+ space = name[:i]
+ local = name[i+1:]
+ }
+ for _, attr := range n.Attr {
+ if attr.Name.Local == local && attr.Name.Space == space {
+ return attr.Value, true
+ }
+ }
+ return "", false
+}
+
+// 给节点添加属性值
+func addAttr(n *Node, key, val string) {
+ var attr xml.Attr
+ if i := strings.Index(key, ":"); i > 0 {
+ attr = xml.Attr{
+ Name: xml.Name{Space: key[:i], Local: key[i+1:]},
+ Value: val,
+ }
+ } else {
+ attr = xml.Attr{
+ Name: xml.Name{Local: key},
+ Value: val,
+ }
+ }
+
+ n.Attr = append(n.Attr, attr)
+}
+
+// 给节点添加子节点
+func addChild(parent, n *Node) {
+ n.Parent = parent
+ if parent.FirstChild == nil {
+ parent.FirstChild = n
+ } else {
+ parent.LastChild.NextSibling = n
+ n.PrevSibling = parent.LastChild
+ }
+
+ parent.LastChild = n
+}
+
+// 给节点添加兄弟节点
+func addSibling(sibling, n *Node) {
+ n.Parent = sibling.Parent
+ sibling.NextSibling = n
+ n.PrevSibling = sibling
+ if sibling.Parent != nil {
+ sibling.Parent.LastChild = n
+ }
+}
+
+// 从reader里面加载xml文档
+func LoadFromReader(r io.Reader) (*Node, error) {
+ var (
+ decoder = xml.NewDecoder(r) //// xml解码对象
+ doc = &Node{Type: DocumentNode}
+ level = 0
+ declared = false
+ )
+ var prev *Node = doc
+ for {
+ tok, err := decoder.Token()
+ switch {
+ case err == io.EOF:
+ goto quit
+ case err != nil:
+ return nil, err
+ }
+
+ switch tok := tok.(type) {
+ case xml.StartElement:
+ //if !declared { // if have no xml node,we also need add children
+ // return nil, errors.New("xml: document is invalid")
+ //}
+ // if there is no xml node.then create it
+ if declared == false {
+ level++
+
+ tmpNode := &Node{Type: DeclarationNode, level: level}
+ addAttr(tmpNode, "version", "1.0")
+ addAttr(tmpNode, "encoding", "UTF-8")
+ declared = true
+ if level == prev.level {
+ addSibling(prev, tmpNode)
+ } else if level > prev.level {
+ addChild(prev, tmpNode)
+ }
+
+ prev = tmpNode
+ }
+ node := &Node{
+ Type: ElementNode,
+ NodeName: tok.Name.Local,
+ Namespace: tok.Name.Space,
+ Attr: tok.Attr,
+ level: level,
+ }
+ //fmt.Println(fmt.Sprintf("start > %s : %d", node.Data, level))
+ if level == prev.level {
+ addSibling(prev, node)
+ } else if level > prev.level {
+ addChild(prev, node)
+ } else if level < prev.level {
+ for i := prev.level - level; i > 1; i-- {
+ prev = prev.Parent
+ }
+ addSibling(prev.Parent, node)
+ }
+ prev = node
+ level++
+ case xml.EndElement:
+ level--
+ case xml.CharData:
+ node := &Node{Type: TextNode, NodeName: string(tok), level: level}
+ if level == prev.level {
+ addSibling(prev, node)
+ } else if level > prev.level {
+ addChild(prev, node)
+ }
+ case xml.Comment:
+ node := &Node{Type: CommentNode, NodeName: string(tok), level: level}
+ if level == prev.level {
+ addSibling(prev, node)
+ } else if level > prev.level {
+ addChild(prev, node)
+ }
+ case xml.ProcInst: // Processing Instruction
+ if declared || (!declared && tok.Target != "xml") {
+ return nil, errors.New("xml: document is invalid")
+ }
+ level++
+ node := &Node{Type: DeclarationNode, level: level}
+ pairs := strings.Split(string(tok.Inst), " ")
+ for _, pair := range pairs {
+ pair = strings.TrimSpace(pair)
+ if i := strings.Index(pair, "="); i > 0 {
+ addAttr(node, pair[:i], strings.Trim(pair[i+1:], `"`))
+ }
+ }
+ declared = true
+ if level == prev.level {
+ addSibling(prev, node)
+ } else if level > prev.level {
+ addChild(prev, node)
+ }
+ prev = node
+ case xml.Directive:
+ }
+
+ }
+quit:
+ return doc, nil
+}
diff --git a/.svn/pristine/5e/5e69ecefe93f6f0a7f5115c7b8607aed51ee86b3.svn-base b/.svn/pristine/5e/5e69ecefe93f6f0a7f5115c7b8607aed51ee86b3.svn-base
new file mode 100644
index 0000000000000000000000000000000000000000..f3af9ddcfc29fa287786d95ad46d964dea4f363b
GIT binary patch
literal 2239542
zcmeI*J+354wjkz9f*4RDMi^m)0tO&Tpg?s-xFW>@2-FU!9KD)SppTz%TTL*aOP|6Cmcuq;$V)&ABk_8X0wQaiU!PY)3H$-Lc8Nq#=_*n$QD
z0t5&UAV7csfnx>wqx*ctQO~`l?E0e+`B#|`bxoY-qo*Fo+Y@rF4%(A^Dk!Q+nivQB
znAj(u>W(@kvMpiDLXlX#Y|Do};2|1UH=elqw39>GX+I`)rdPJyO}}bZfnV>IOj^Kw
zGEb{SE!NlXX$vk15FkK+009C72plWWAIs+}j(YS>B~1HVsZMXJt+K%sbFlvEbE`d3
z0`vn?-BF&wwbemSoyvzkV9LBis7q9VjWqf+(#C66QEv3(lfz_fRg(|Qw6)%z=(wUCO^|C$rr-Gu&^wm=;
z0s7?Ih1&Kd>Z|2LznvQPQvKE5U953+A0mqfB*pk1PBlyK;R?-{n35C;)wTp#nC;Thf`@#x0%lWb;{QDSFIP?M|Hh<
zDj!aw(U%gb_DRTn+EqB7LMH#}Fj;EVrN4gt93K{|9}P>t$7`1WcgQ?_y~S(VFCDiu
z2oNAZfB*pk1PGi&pg+3Tvwa+}OP=Y(TQAdrJj$F@8pJl+(|(Q6E-^W)KT)SLq))y^
zu60Kpobs%f@y@+eKJ)<((YU(t#MP(WI+T~7ufO`9`bx#p{l*i19iISWdc5vw*8Q26
z$YquEkS^^vR@WdvfB*pk1PBlya4LcR=zi(o9Tiraf7Cc}x1V0d*VBGHj=5BSwG~;J
zb@edcCtoAiWZHJ*oTjAmA>A#r`t8&$$9^MnX{@Djb>lUws3QBc)86}PtM-&?G=h};
z>#TU0QrJ{U)r}{>9Ww9ptb2(EvNbWk6Cgl<009C72oN}-Ks{r()kN)yLwLz~^57kN
zN%crA4ch4uAy%p9{I=SfoOSgu-zT4vDG}0xk`yzQ4}HKxG*XfQ7-E$xN~b>U#xdNiqrbz+v+RczDD)+trII?!mk4o;69nx
z``@GNibgx8WYPxNC-Xj<!DOHUR5laugH%2in1;N0t5&UAV7cs
zfwKvWpZvGZeCzUIB>x>WCaai|TPdv4qshsH>-72rZT#zEj!nOdpy5I87z{yf8y<@OMj<+?oG3x`SQi7#L
zZv|W>^IDX}`yT6;Q+=OdP_nT`Wqa*4AIk09VXB5-3^Cq}}dRn*ad<1PBlyK!5-N0t5&UAV7cs
z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ
zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U
zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7
z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N
z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5)0N8rJFrrF|NONk@c#Dp@%8gYugjxo
zEZF`&fC~~cg#ZBp1PBlyK!CvO2#i-8XLv?dvOP)tbq0+EU!_|EE=b7~0t5&UAV7cs
z0Rpchp#ExK>&Mb)GaqcLzXqWUBS3%v0RjXF5Fk(l>buB3zI+OezGSFx7yR<+t&VBm
zJy_mE_~qkEc{5?$jp?PYzQM2j9(UUa?Gv9mt4*Vh{QR}NQ?Wdu`u*4E_qWeq%bNz@
zV`86t&8>|5`1sncRU?$&Qzof==mW-fYP9nE4jN^Z`Hd&8KJDJ2aJ;>Lt_}fM7OJ6Y
zf9n?ejYdtWom;234-kWE=G8B=+GNVo{kro5()J@m4FUuR5FkK+009Cg7wC`fafFV{
z+lr$ej7!<|M>98=$xoiB)5IuAVq%|ssyphG$hPdLEEI{=
z%eH*z10JGrb>oSvPdho3o%Ul=XL@DJ-Sn$w75MdT$)p9WiM4fZ+Dn;LbBhEuBv+H@dmM!%-ol2PYyj`ca)mGViidh4;OH7`q
z``l_zOza2L$gz5P3e#2x{i{&cZ3pxLQ|2YY4jO$LY2%5jAD
zh!Dr}Iwi`en3djt*q_5w3D75BBiDu6c3EQbSIKtW`fC-9s~b-R$h@_+~-
zK4s~6GL^&4p?w&+rpZY6Go|dI9{q^hT_^?=ct@~f`
z+9klNul{5aSLN#qadki$Jh@7{3vB`f2oNAZfB*pk=M=cL;wZbQ)l)i?$2$@)osHYm
z{+{($%Cla^gSJ#YoJ3=X`YTn$@x>WS*Vi%XtTJG-GD?6~U;W7-C3ulnf5oeyL4W`O
z0t5&UAn>dLBNazIGe?EhQq)_esEND%xxI|9r~Rw%KWtC?WmePzv0^&C_sO>p8qzSO+D#O~2oNAZfB*pk1PGj5pq{a#dMer0o;ZY;p2>rE>?_qH^=#Zuj|j0!
zJ!7}k*5s@>lc%*}VxN3UrbI}eW=b*3y8ZhPBhRw#AsQ*k0E~^N0_3VgTLD$fsK46n
zmvvJ`)@CyKWsm?TU&sDMX%{W|q`I$Nv}T(Ir0v%+ekVYH009C72oNA}et~*)k5hL&
z=$6a!tDg4jLA^aNm*e!8Pw%m{bXu-w<1#%;uo|9eiuGXv80BU=pu1PBlyK!5-N0w))!NB2@tl{0@mgqPpzd(!%z*h?I<
z>y-9AZ1q;Dt=chhmaY*l)n8vr8h`wZ;CkS{T87LdAE}l`yOFl&E4NCLef@Q~#?_5i
z+hCt}i0Uj}--=NB+r779Z9B@YXtZ||U`=fP)vwdr7bSgpTpf_M-{zxDfB*pk1PBly
zK!89J==P#ejx4oP%V59zOH@JFR{k1x&fCLB-
zAV7cs0Rm4fFn;pi8sU}euVPyYtI20iiM^I@_3@edE8(~#K!5-N0t5&UAaHU4^;i1>
zEzqcMDNLnM8?$eh_xnwjTIs!xC33v2u?OPOwkAsAV7cs0RjXF5Fqf%0^k4nA3uCk>a4#f
zgvt8rFF${L`^_(Z{qrw%@J}D*^4E_ae~r0i*0*luNPM)L%-lQZc1ref?E>QdQO0U$I0#J#N)T&7l@+?eBm2t`vj+
zNP}GxAV7cs0RjXF5FkL{R05^cO79rFRO8for!BZ@CDl%E3#b~Wy<0aP_16zSex!$J
zrKW2usS>TdEYtfbrLzWX6FZf#WC#!-K!5-N0t5&UAP@reNme|}O3%4s*rooqN{ad`
zimaF(jkr}CZGqO-Ur|++nk$~5P1au}a;#h1YO&DPAV7cs0RjXF5FkL{oC5!ROW}{d
zj=cY{-9pq&wGOJ4TKfsFc5u{RrL#P$EXkL$
ztN)BxlvHIvt0t8|uKYf$}
z@Yfo)mQ;T&JyYL+v8D5)ZDF=U-*NwUlc&o}N;b
z%OA?y6uYq7tphX4Tr1PBlyK!5-N0;d%yZ}9t}d~&M$
zdCD^hFRQ=mI|<7(vhTn9r7xf^)n75If4G)<;;oD`nY%@R009C72oNAZfB=C*1mZ(m
zrI4uw(R{HJAIn-+f7MxKt@^mFJjO}|RJ!bIv{34wwZ$zB0t5&UAV7cs0RjXFoKT>A
z(yD$wt5incfA?GY{)BCklSNh?5S3J_nEK23{8yb=9&(j2x4zx6&8oK5U%iPQ0t5&U
zAV7cs0RjZhEKr|z)o*`MzahrQ$3G(Bnffcnw2hIPsII8~YTdL65FkK+009C72oQJ?
zfl@TZPdZMIz}Bt5%0lVsSb8)z30|L%p7009C72oNAZ;DH3vBe2N)QvDSJQe&hhO7&NYFn&3*)_61{2@oJa
zfB*pk1PBlyu#Z5kv-)rLzD51D&yK7@fB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+
z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly
zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF
z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oQL2fuBA;
zzWwIcZ@>9l`ri-V{O#l8?=OyH`veFOAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly
zK!5-N0t5&UAVA;@0^k1W??3&iysytM0t5&UAV7cs0RjXFJh{O4fBwf`zANR=KgvE!
zDO5l46g_|WxqK4pm(aP(cV+ar+K!5-N0t5&Ucmjd8
z{;Jz4HP`pw{POYhZ|&}CAvRxLl}aiKw{~u{`?bogzW%B;-CzIwOPyF|mHMt-x_*C*
zSgZYZ8Rc7K{Pa<($Y0}`+7CaL67rwlNh79|$XCNg+HIqjsF7R5Da$Rp)dp|dHCoL)
z_RTEG1-mIbv`OXiLjr${pAyXbI%~t_^sAM%cAeM;1^`Jgjf7J@8eL_?pc(pwdxvja{b{$YRK3Sne
zgwkkNEXlWp(z07^@X}5()7^9#Pxt22o*%Yd{gtwHNq_(W0t5&UAVA>71!@`6KaHxT
zRuo5VQFcjevb<^sPY#GBV&t9mS4}n5U$wJrGs>mK^;gNW%q?+#`19`{e2Y4<=D+M#
z?0v8XEaRi3N;{2EwJ|bG{gu#M5+Fc;009C72oTsvps$JAQY(t1)Y;c-^F6gj=+`Qn
ziX~!$H`QNta9dc_RHG`XmyuqSOC_1o**?*$Bj+C^)g)ule(0U~xaJ)1%$$stI@_;@bju|H0t5&UAV7cs0Roo<`kJUcT1Rozc8-TiBcmdS
zYG|f0UMSVvQm9&+L^V|IM!=d?P3F$}tFKvN#hY#g)YbZ{rafPIm1u**>bisVS8Od&
zm&m$xF+SxGC0^=}%bNRz@y(;YRB5l#fdS1PBly
zK!5-N0tCuoKAra4qjeNVZRZTy{7JsvO;tlI5n)r$KZ~8_XEe`0Bx>*0v?rey-5NI1
zYvY$7?W3P%w<2GP;FHbw)LFfzk99kX)C5$kCZXBaEl;Op_HoUr$7DkhlQ23((3JHnfsSN
zm7i<&`wyGG8aC2SjTEr__~`b}PlN8*Bkf4HcVBgQL8P9MXV#IX|qfIQf)tGFs_W
ze_fK%Pk;ac0t5&UAV6S7Aj*(b1dY7^@Y38Gsz1-ybN;gDUnQSX-9(b99*O#*4oG*~
zJmXgFoDbW()md$MSeGt6%Wm~c)SfoycDc#%C5QR?tIoPKO#L;fs*?Z#0t5&UAV7e?
z83b;6_EFCKQHb4Hf33UssK3??`-ssN)L)OdO*s=FK!5-N0t5&UI98y2$P$m1<{Rbd
zmHO-0S8c7;>!;Pq3#$HFi&Pu}1PBlyK!5-N0^G@ZC
z>r%UY$K6H`sx}Intj>QKHF&&C=g(P&1PBlyK!5-N0t6mipgsg?3!k#1dN@y?*t)dS
zQofaXDn4L!X;|tnpXy4BrU4rjN*jeu$v?_v(NKRq%8MmW0t5&UAV7csfhQ0sPrLr|
zUHLA8zkhGQ_Sg4+`uoSv<$DHR`BjUrk?#VL0$r`Y(s-8y2oNAZfB*pk1PBm#ae?xt
z#2>!-_2c93FYaLb1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly
zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF
z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk
z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs
z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fn5Q{`&Fp?RUR@
z`_13#|2}^FH4Sh{fB*pk1PBlyK!5-N0;>yr`=`JE<-5OqeEehe$N~}|K!5-N0t5&U
zAV7dXEAaiF|DpbBL9_`FAV7cs0RjXF5FoITfck4ASYZheAV7cs0RjXF5Fn5Q)L#k2
zB>@5i2oNAZfB*pk1nv|lpYw`uxG~uH=}+ZzVSW)HK!5-N0t5&UAV7e?Is%@5t>Y*P
z0RjXF5FkK+009C7t_jrdMgPM$}0t5&UAV7cs0RjXF^aARy
z-b4=p0t5&UAV7cs0RjZJ5UBOn%sUU$EziHUcooDXK!5-N0t5&UAVA=i1Zj>d{=(>*FWxwV=ePBlyK!5-N0t5)m3zRn{
z{!qRtho8JW&*Uxv0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U
zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7
z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N
z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+
z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly
zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF
z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk
z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs
z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fqd@0&kzbeEIbD
zEW5D}0t5&UAV7cs0RjXF953+x`Rk{*QfGZhsZ7>ipTB;*y}f_^{9Xr_Id5;DKE8a4
zxnz%gX
zs+Ckby)B?>oc3;2i2Cc(myh%i?T@nWUzJpemI|wWN{LwmwuzmWTV@0Z5FkK+009C7
z2)wpHeUcRqvufScmou08+bSvQuPCy5+PGC4ZGqO-Ur|++nk$~5P1av!iCDL``{esH
z^bjCGfB*pk1PBlyK;S@uf4-%#R78IiLMf9=^;a1dbyKZ_>d5vJUTvtTzv{%Ot=c%X
zU7wD%>!$jvT-FCaw*IOy;}KYtQStCAg4bHCt-sQkGV;@x@{zRn$)($kXcHhnfB*pk1PBly
zK;RI8Qu5RfcEw|(OLbQ2PnRY6Qg-#95sQ+l45&3)TYr_#Qc}gzF}O6^kA~InpjZm4
zw*HF2;Z}OQ^Ds0t2oNAZfB*pk1PBl~p+Nhl!BPs98m7GeuvSw2?@{2?`l}z%_r&+m
zD3#ZHS**nWg9uchaY){K=$T{Adt5gT`vi0`qb1A+4t?Y{NX>j!SjZ(YCyB7PqdI%68K!5-N
z0t5&UAaGiN@&>>1O*i_Vr#zGJvihsOldu$E@9*z@0d=YVidp@`wbT=DWt_>}Edm4x
z5FkK+009C72pl31AKEH~Of87!i=Fsb*0TDm&MIrw$8F^?Rw|&G{_^&!kfQH4|zwr4Uem1%(Cy0t5&UAV7cs0Rj&skRE|W=9lWP
z7?2txHBqX+QiSo#k+sI78A*Tu0RjXF5FkK+0D*l3YMs@8v-d6PuYGo86#@hZ5FkK+
z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly
zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF
z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk
z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0xvG`?Kgj$
z|KE%I*ggRQ1PBlyK!5-N0(%O~mnY@!p2@7W*40h*1J+tv90CLg5FkK+009C72qb~N
z0J++eBAoN`>MrI7oO4sMB0zuu0RjXF5FkL{K?UXukgIo3yX&i&j}JKQ9wkPA009C7
z2oNAZfWV^&j29qRN1kfSSF>F<;8c5*3;_ZJ2oNAZfB*pkk0P+F0J%Er4BNja$$RFW
zVefJvK!5-N0t5&UAVA=30{2uI_sreFVJ5wsR$nX5O^X^#fB*pk1PBlyK!CuL39MCF
ztQBWP-b*PhUSjoti!(8i009C72oNAZfWXTNTsoH5{xh>&%6xIos|Q>+lf}{6iIaP5
z2WS%@K!5-N0t5&UAh5c?%?CMT(fO3zB|v}x0RjXF5FqfN
z0{!W__AJ}Zy3rQo&?m4U$gNX$TQn_nYo3e8AGPk{giRzsfB*pk1PBlya6*A}uCAB&
z=ebeXk;Kx{BU4rxv%|V+iE_D0<|9E4TzVuuV+ar+K!5-N0t5)0U!Xr!uXv>2H25Xk
ze$h)KSMT3p>9oY^TbK`c?CSHmxl4cm0RjXF>>!X11L<;y1S~<|(FM|8$
zx#-`gvGwX($Ddb9tC!39@$M2JK!5-N0uL?F|I>d{&qMEB@&vXJNPmL1Sfa+R=l4Ft_s?J7-`+mHey+E^etf*We}4P7U+t|r;O*0w
zf4lh>cSmyQm)1jo009C72t1HL`se=s%Lm%KR0(V+kp3ubw@{6|&vN^$GH#r}R_Yfy<2)la)_831PBlyK!Cu*38a7P`^!r^>PNOc
zmuBfF@FD{3ABWoBdgJ@7m{!?(QDy5FkL{VFlWMs|OS8oieasye-C>D-
zU#Vxi97ZB9uD{AI$}_K-`m09%FaPnswrQljyCgt>009C79#^3KC%$bj*ik#ZZ7&FA
z$|ZpocCdXZl>QwA(rdKCie-r%7HyaKPyhLE_kR+qzE3Yc2Guq$l`3rxrM;r