{"id":212701,"date":"2014-04-01T11:07:02","date_gmt":"2014-04-01T07:07:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=212701"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=212701","title":{"rendered":"<span class=\"post_title\">NanoMMO \u043d\u0430 Go \u0438 Canvas [\u0421\u0435\u0440\u0432\u0435\u0440]<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/22b\/f02\/52a\/22bf0252aed3b2161b7b8613ae525417.png\"\/><br \/>  \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e <s>cms<\/s>, <s>framework<\/s>, mmorpg. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438\u043c \u043c\u044b \u0438 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f.<br \/>  <a href=\"http:\/\/tatrix.org\/nanommo\/\"><b>\u0414\u0435\u043c\u043e<\/b><\/a><a name=\"habracut\"><\/a><\/p>\n<h4>\u0423\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u0438<\/h4>\n<p><sub>\u0414\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u0437\u043d\u0430\u0442\u044c Go, \u043b\u0438\u0431\u043e \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0438-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0435\u0431\u0435 \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 js.<br \/>  <a href=\"http:\/\/tour.golang.org\/\">\u0412\u0432\u043e\u0434\u043d\u044b\u0439 \u0442\u0443\u0440 \u043f\u043e Go<\/a><br \/>  <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Guide\/HTML\/Canvas_tutorial\">\u0422\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u043f\u043e \u043a\u0430\u043d\u0432\u0430\u0441\u0443<\/a><br \/>  \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u2014 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0432 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043c\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u044b\u0441\u043b\u0438. \u041d\u0435 \u0432 \u043a\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0435\u0437\u0434\u0443\u043c\u043d\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/sub><\/p>\n<h4>\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0437\u0430\u0434\u0430\u0447\u0435\u0439. \u041d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441 \u043c\u0430\u043b\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0443\u043c\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0432\u0441\u044e \u0438\u0433\u0440\u043e\u0432\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0443.<\/p>\n<p>  \u0421\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b, \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043c\u0438\u0440\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0435\u0442\u043e\u0440\u043e\u043f\u043b\u0438\u0432\u043e\u0441\u0442\u044c\u044e TCP. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438, \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 json&#8217;\u0435.<\/p>\n<p>  \u041f\u0435\u0440\u0432\u0430\u044f \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0430\u044f \u043c\u043d\u0435 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043c\u044b\u0441\u043b\u044c \u2014 \u043d\u0430\u043f\u0438\u0448\u0443 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0430\u043a \u044f \u0438 \u0441\u0434\u0435\u043b\u0430\u043b. \u041d\u043e \u043c\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443; \u0434\u0430\u043b\u044c\u0448\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443.<\/p>\n<h4>\u0421\u0435\u0440\u0432\u0435\u0440<\/h4>\n<p>\u041d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<ul>\n<li>\u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432<\/li>\n<li>\u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043c\u0438\u0440\u0430<\/li>\n<li>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0446\u0438\u043a\u043b, \u0438\u0437\u043c\u0435\u043d\u044f\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0438\u0440\u0430<\/li>\n<\/ul>\n<p>  \u041f\u043e\u0434 \u043c\u0438\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \u0438 \u0442\u043e\u043b\u044c\u043a\u043e. \u041d\u0438 \u043a\u0430\u0440\u0442\u044b, \u043d\u0438 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0433\u0440\u043e\u043a\u0438. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u0431\u0443\u0434\u0443\u0442 \u0443\u043c\u0435\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0438, \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u043a \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435.<br \/>  \u0422\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"go\">\/* point.go && character.go *\/  ... type Point struct { \tX, Y float64 } ... type Character struct { \tPos, Dst Point   \/\/\u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0442\u043e\u0447\u043a\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \tAngle    float64 \/\/\u0423\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \tSpeed    uint    \/\/\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \tName     string } ... <\/code><\/pre>\n<p>  \u041d\u0430\u043f\u043e\u043c\u043d\u044e \u0447\u0442\u043e \u0432 go, \u043f\u043e\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u0443\u043a\u0432\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438 (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c\u0438), \u0430 \u043f\u0440\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 json \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f. (<i>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u043b \u043d\u0430 \u044d\u0442\u0438 \u0433\u0440\u0430\u0431\u043b\u0438, \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044f \u043f\u043e\u0447\u0435\u043c\u0443 \u0441 \u0432\u0438\u0434\u0443 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0441 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0431\u0443\u043a\u0432\u044b<\/i>).<\/p>\n<p>  \u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u043a\u043e\u0434\u0430, \u0432\u0438\u0434\u0430 <code>character.x = data.X<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0438 \u0431\u0443\u0434\u0443\u0449\u0438\u0445 \u043f\u043e\u043b\u0435\u0439, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u043f\u043e\u043b\u044f\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438, \u043f\u0440\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439, \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c. \u041d\u043e \u043f\u043e\u043b\u044f \u0432 go \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u0443\u043a\u0432\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u0438\u043c\u0435\u043c \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043e\u0431 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u0435\u0439 \u0432 js \u0432 \u0441\u0442\u0438\u043b\u0435 go. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e \u044d\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0441 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<h5>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0446\u0438\u043a\u043b<\/h5>\n<pre><code class=\"go\">\/* main.go *\/ package main  import ( \t&quot;fmt&quot; \t&quot;time&quot; )  const ( \tMAX_CLIENTS = 100 \/\/\u0421\u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \tMAX_FPS     = 60 \t\/\/ \u0412\u0440\u0435\u043c\u044f \u0432 go \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 \t\/\/ time.Second \u044d\u0442\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0435 \tFRAME_DURATION = time.Second \/ MAX_FPS )  \/\/ \u041a\u043b\u044e\u0447\u0430\u043c\u0438 \u044d\u0442\u043e\u0433\u043e \u0445\u044d\u0448\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u043d\u0430 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 var characters map[string]*Character  func updateCharacters(k float64) { \tfor _, c := range characters { \t\tc.update(k) \t} }  func mainLoop() { \t\/\/ \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0438 \u0434\u0432\u0438\u0433\u0430\u043b\u0438\u0441\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0436\u0435\u043b\u0435\u0437\u0430 \u0438 \t\/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \t\/\/ \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0435\u043d\u0442\u0430, \u043c\u044b \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \tvar k float64 \tfor { \t\tframeStart := time.Now()  \t\tupdateCharacters(k)  \t\tduration := time.Now().Sub(frameStart) \t\t\/\/ \u0415\u0441\u043b\u0438 \u043a\u0430\u0434\u0440 \u043f\u0440\u043e\u0441\u0447\u0438\u0442\u0430\u043b\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0435\u043c \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f \t\tif duration &gt; 0 && duration &lt; FRAME_DURATION { \t\t\ttime.Sleep(FRAME_DURATION - duration) \t\t} \t\tellapsed := time.Now().Sub(frameStart) \t\t\/\/ \u041a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u044d\u0442\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u0430\u0434\u0440\u0430 \u043a \u0441\u0435\u043a\u0443\u043d\u0434\u0435 \t\tk = float64(ellapsed) \/ float64(time.Second) \t} }   func main() { \tcharacters = make(map[string]*Character, MAX_CLIENTS) \tfmt.Println(&quot;Server started at &quot;, time.Now())  \t\/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432 \tgo NanoHandler() \tmainLoop() }  <\/code><\/pre>\n<p>  \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 Character.update \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0443\u0434\u0430 \u0438\u0434\u0442\u0438:<\/p>\n<pre><code class=\"go\">\/* point.go *\/ ... \/\/ \u0427\u0438\u0441\u043b\u0430 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \/\/ \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438\u0445 \u0440\u0430\u0437\u043d\u043e\u0441\u0442\u044c func (p1 *Point) equals(p2 Point, epsilon float64) bool { \tif epsilon == 0 { \t\tepsilon = 1e-6 \t} \treturn math.Abs(p1.X-p2.X) &lt; epsilon && math.Abs(p1.Y-p2.Y) &lt; epsilon } ... \/* chacter.go *\/ ... func (c *Character) update(k float64) { \t\/\/ \u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u0442\u043e\u0447\u043a\u043e\u0439 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \t\/\/ \u043c\u0435\u043d\u044c\u0448\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0437\u0430 \u044d\u0442\u043e\u0442 \u043a\u0430\u0434\u0440 \t\/\/ \u0438\u043b\u0438 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442 \u043d\u0438\u043a\u0443\u0434\u0430 \u0438\u0434\u0442\u0438, \t\/\/ \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u0442\u043e\u0447\u043a\u0443 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \tif c.Pos.equals(c.Dst, float64(c.Speed)*k) { \t\tc.Pos = c.Dst \t\treturn \t} \t\/\/ \u0423\u0440\u0430! \u041d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u0448\u043a\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u0443\u0440\u0441 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438 \u0438 \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0438 \t\/\/ \u0412\u043f\u0440\u043e\u0447\u0435\u043c \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u0443\u0433\u043b\u0430 \u0438 [\u043a\u043e]\u0441\u0438\u043d\u0443\u0441\u043e\u0432, \u043d\u043e \u0443\u0433\u043e\u043b \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u0435\u043d \u0432 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435 \t\/\/ \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043f\u0438\u0448\u0438\u0442\u0435 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0438 \tlenX := c.Dst.X - c.Pos.X \tlenY := c.Dst.Y - c.Pos.Y \tc.Angle = math.Atan2(lenY, lenX) \tdx := math.Cos(c.Angle) * float64(c.Speed) * k \tdy := math.Sin(c.Angle) * float64(c.Speed) * k \tc.Pos.X += dx \tc.Pos.Y += dy } ... <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u043c.<\/p>\n<pre><code class=\"go\">\/* nano.go *\/ package main  import ( \t&quot;code.google.com\/p\/go.net\/websocket&quot; \t&quot;fmt&quot; \t&quot;io&quot; \t&quot;net\/http&quot; \t&quot;strings&quot; )  const ( \tMAX_CMD_SIZE  = 1024 \tMAX_OP_LEN    = 64 \tCMD_DELIMITER = &quot;|&quot; )  \/\/ \u041a\u043b\u044e\u0447\u0438 \u2014 \u0430\u0434\u0440\u0435\u0441\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0432\u0438\u0434\u0430 ip:port var connections map[string]*websocket.Conn  \/\/ \u042d\u0442\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 json \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 type packet struct { \tCharacters *map[string]*Character \tError      string }  \/\/\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 func NanoHandler() { \tconnections = make(map[string]*websocket.Conn, MAX_CLIENTS) \tfmt.Println(&quot;Nano handler started&quot;) \t\/\/\u0421\u0441\u044b\u043b\u043a\u0438 \u0432\u0438\u0434\u0430 ws:\/\/hostname:48888\/ \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 NanoServer \thttp.Handle(&quot;\/&quot;, websocket.Handler(NanoServer)) \t\/\/\u0421\u043b\u0443\u0448\u0430\u0435\u043c \u043f\u043e\u0440\u0442 48888 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u0445 \terr := http.ListenAndServe(&quot;:48888&quot;, nil) \tif err != nil { \t\tpanic(&quot;ListenAndServe: &quot; + err.Error()) \t} }  \/\/\u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u0435\u0442\u0435\u0432\u043e\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f func NanoServer(ws *websocket.Conn) { \t\/\/\u041f\u0430\u043c\u044f\u0442\u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u043f\u043e\u0434 MAX_CLIENTS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0446\u0438\u043d\u0438\u0447\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u0445, \u043d\u0430 \u043a\u043e\u0433\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043c\u0435\u0441\u0442\u0430 \tif len(connections) &gt;= MAX_CLIENTS { \t\tfmt.Println(&quot;Cannot handle more requests&quot;) \t\treturn \t}  \t\/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 127.0.0.1:52655 \taddr := ws.Request().RemoteAddr  \t\/\/\u041a\u043b\u0430\u0434\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \tconnections[addr] = ws \t\/\/\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044f \u0435\u0433\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \tcharacter := NewCharacter()  \tfmt.Printf(&quot;Client %s connected [Total clients connected: %d]\\n&quot;, addr, len(connections))  \tcmd := make([]byte, MAX_CMD_SIZE) \tfor { \t\t\/\/\u0427\u0438\u0442\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \t\tn, err := ws.Read(cmd)  \t\t\/\/\u041a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \t\tif err == io.EOF { \t\t\tfmt.Printf(&quot;Client %s (%s) disconnected\\n&quot;, character.Name, addr) \t\t\t\/\/\u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446 \t\t\tdelete(characters, character.Name) \t\t\tdelete(connections, addr) \t\t\t\/\/\u0418 \u043e\u043f\u043e\u0432\u0435\u0449\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0433\u0440\u043e\u043a \u0443\u0448\u0435\u043b \t\t\tgo notifyClients() \t\t\t\/\/\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u0446\u0438\u043a\u043b \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \t\t\tbreak \t\t} \t\t\/\/\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \t\tif err != nil { \t\t\tfmt.Println(err) \t\t\tcontinue \t\t}  \t\tfmt.Printf(&quot;Received %d bytes from %s (%s): %s\\n&quot;, n, character.Name, addr, cmd[:n])  \t\t\/\/\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0442\u0430\u043a: operation-name|{&quot;param&quot;: &quot;value&quot;, ...} \t\t\/\/\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \t\topIndex := strings.Index(string(cmd[:MAX_OP_LEN]), CMD_DELIMITER) \t\tif opIndex &lt; 0 { \t\t\tfmt.Println(&quot;Malformed command&quot;) \t\t\tcontinue \t\t} \t\top := string(cmd[:opIndex]) \t\t\/\/\u041f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u0438\u0434\u0443\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \t\t\/\/\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0431\u0435\u0440\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e n \u0431\u0430\u0439\u0442 \t\t\/\/\u0412\u0441\u0435 \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u043c\u0443\u0441\u043e\u0440, \u0438 \u0435\u0441\u043b\u0438 \u043d\u0435 \u043e\u0442\u0440\u0435\u0437\u0430\u0442\u044c \u043b\u0438\u0448\u043d\u0435\u0435, \t\t\/\/\u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f json \t\tdata := cmd[opIndex+len(CMD_DELIMITER) : n]  \t\t\/\/\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \t\tswitch op { \t\tcase &quot;login&quot;: \t\t\tvar name string \t\t\t\/\/\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043d \t\t\twebsocket.JSON.Unmarshal(data, ws.PayloadType, &name) \t\t\t\/\/\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u043d\u0435\u0442 \u043e\u043d\u043b\u0430\u0439\u043d \t\t\tif _, ok := characters[name]; !ok && len(name) &gt; 0 { \t\t\t\t\/\/\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e \t\t\t\tcharacter.Name = name \t\t\t\tcharacters[name] = &character \t\t\t\tfmt.Println(name, &quot; logged in&quot;) \t\t\t} else { \t\t\t\t\/\/\u0418\u043d\u0430\u0447\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u043c\u0443 \u043e\u0448\u0438\u0431\u043a\u0443 \t\t\t\tfmt.Println(&quot;Login failure: &quot;, character.Name) \t\t\t\tgo sendError(ws, &quot;Cannot login. Try another name&quot;) \t\t\t\tcontinue \t\t\t} \t\tcase &quot;set-dst&quot;: \t\t\tvar p Point \t\t\t\/\/\u0418\u0433\u0440\u043e\u043a \u043d\u0430\u0436\u0430\u043b \u043a\u0443\u0434\u0430-\u0442\u043e \u043c\u044b\u0448\u043a\u043e\u0439 \u0432 \u043d\u0430\u0434\u0435\u0436\u0434\u0435 \u0442\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u0441\u044f \t\t\tif err := websocket.JSON.Unmarshal(data, ws.PayloadType, &p); err != nil { \t\t\t\tfmt.Println(&quot;Unmarshal error: &quot;, err) \t\t\t} \t\t\t\/\/\u0417\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0443 \u0442\u043e\u0447\u043a\u0443 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \t\t\t\/\/\u0422\u043e\u0433\u0434\u0430 \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435, \u043c\u0435\u0442\u043e\u0434 Character.update \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \t\t\tcharacter.Dst = p \t\tdefault: \t\t\t\/\/\u041e\u0439 \t\t\tfmt.Printf(&quot;Unknown op: %s\\n&quot;, op) \t\t\tcontinue \t\t} \t\t\/\/\u0418 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u043f\u043e\u0432\u0435\u0449\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \t\t\/\/\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u0432 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u044b\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \t\tgo notifyClients() \t} }  \/\/\u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 func sendError(ws *websocket.Conn, error string) { \t\/\/\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0430\u043a\u0435\u0442, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \tpacket := packet{Error: error} \t\/\/\u041a\u043e\u0434\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0432 json \tmsg, _, err := websocket.JSON.Marshal(packet) \tif err != nil { \t\tfmt.Println(err) \t\treturn \t}  \t\/\/\u0418 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \tif _, err := ws.Write(msg); err != nil { \t\tfmt.Println(err) \t} }  \/\/\u041e\u043f\u043e\u0432\u0435\u0449\u0430\u0435\u0442 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 func notifyClients() { \t\/\/\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0430\u043a\u0435\u0442 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439 \tpacket := packet{Characters: &characters} \t\/\/\u041a\u043e\u0434\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0432 json \tmsg, _, err := websocket.JSON.Marshal(packet) \tif err != nil { \t\tfmt.Println(err) \t\treturn \t}  \t\/\/\u0418 \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u0432\u0441\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \tfor _, ws := range connections { \t\tif _, err := ws.Write(msg); err != nil { \t\t\tfmt.Println(err) \t\t\treturn \t\t} \t} }  <\/code><\/pre>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u0434\u0430\u0442\u044c \u0435\u043c\u0443 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u0412 go \u044d\u0442\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0434\u0435\u043b\u043e \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u0438\u0434\u0430 NewTypename<\/p>\n<pre><code class=\"go\">\/* character.go *\/ ... const ( \tCHAR_DEFAULT_SPEED = 100 ) ... func NewCharacter() Character { \tc := Character{Speed: CHAR_DEFAULT_SPEED} \tc.Pos = Point{100, 100} \tc.Dst = c.Pos \treturn c }  <\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u0438 \u0432\u0435\u0441\u044c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<hr\/>\n<p><i>\u0421\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u0443.<\/i><\/p>\n<hr\/>\n<h4>\u0421\u0441\u044b\u043b\u043a\u0438<\/h4>\n<p><a href=\"http:\/\/tatrix.org\/nanommo\/\"><b>\u0414\u0435\u043c\u043e<\/b><\/a><br \/>  <a href=\"http:\/\/tatrix.org\/go\/diamond-square\/\">\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u0430\u0440\u0442 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043d\u0430 \u0444\u043e\u043d\u0435)<\/a><br \/>  <a href=\"https:\/\/github.com\/TatriX\/nanommo\/\">\u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438<\/a>    \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/212701\/\"> http:\/\/habrahabr.ru\/post\/212701\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/22b\/f02\/52a\/22bf0252aed3b2161b7b8613ae525417.png\"\/><br \/>  \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e <s>cms<\/s>, <s>framework<\/s>, mmorpg. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438\u043c \u043c\u044b \u0438 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f.<br \/>  <a href=\"http:\/\/tatrix.org\/nanommo\/\"><b>\u0414\u0435\u043c\u043e<\/b><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-212701","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/212701","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=212701"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/212701\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=212701"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=212701"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=212701"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}