{"id":290459,"date":"2018-10-08T11:35:02","date_gmt":"2018-10-08T07:35:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=290459"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=290459","title":{"rendered":"\u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043d\u0430 Golang \u0438 gRPC, \u0447\u0430\u0441\u0442\u044c 1"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\n<h3 id=\"vvedenie-v-mikroservisnuyu-arhitekturu\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443<\/h3>\n<p>  <\/p>\n<h4 id=\"chast-1-iz-10\">\u0427\u0430\u0441\u0442\u044c 1 \u0438\u0437 10<\/h4>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0441\u0435\u0440\u0438\u044f \u0438\u0437 \u0434\u0435\u0441\u044f\u0442\u0438 \u0447\u0430\u0441\u0442\u0435\u0439, \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0437 \u0432 \u043c\u0435\u0441\u044f\u0446 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Golang. \u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c protobuf \u0438 gRPC \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. <\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b: golang, mongodb, grpc, docker, Google Cloud, Kubernetes, NATS, CircleCI, Terraform \u0438 go-micro.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u043c\u043d\u0435 \u044d\u0442\u043e? \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430\u043a\u043e\u043f\u0438\u0432\u0448\u0438\u0435\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0422\u0430\u043a \u0436\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0442\u0435\u043c, \u0447\u0442\u043e \u044f \u0443\u0437\u043d\u0430\u043b \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Go \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u043e\u0432\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0433\u0440\u0443\u0437\u044b<\/li>\n<li>\u0438\u043d\u0432\u0435\u043d\u0442\u0430\u0440\u044c<\/li>\n<li>\u0441\u0443\u0434\u0430<\/li>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438<\/li>\n<li>\u0440\u043e\u043b\u0438<\/li>\n<li>\u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/fg\/di\/ez\/fgdiezxwlpd1eghakcgbkgfi3yu.jpeg\" alt=\"image\"\/><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0427\u0442\u043e \u0431\u044b \u0438\u0434\u0442\u0438 \u0434\u0430\u043b\u0435\u0435, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Golang \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (\u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0432\u0430\u043c \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u0438\u043d\u0430\u0447\u0435 \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u0441\u043d\u043e\u0432\u0430\u043c\u0438). <\/p>\n<p>  <\/p>\n<h3 id=\"teoriya\">\u0422\u0435\u043e\u0440\u0438\u044f<\/h3>\n<p>  <\/p>\n<h4 id=\"chto-takoe-mikroservisnaya-arhitektura\">\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430?<\/h4>\n<p>  <\/p>\n<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438\u0437\u043e\u043b\u0438\u0440\u0443\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432 \u0441\u0435\u0440\u0432\u0438\u0441, \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0439 \u044d\u0442\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0414\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0437\u0430 \u0440\u0430\u043d\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<br \/>  \u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043e\u0431\u0449\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u0430, \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/tr\/aq\/dm\/traqdmhafa_yvh0haprr05w7rgo.png\"\/>  <\/p>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u0430 \u0447\u0430\u0441\u0442\u044f\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 &quot;\u0434\u0451\u0440\u0433\u0430\u0435\u0442\u044c\u0441\u044f&quot; \u0447\u0430\u0449\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0435\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432. \u042d\u0442\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u043c \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0435\u0440\u0435\u0437\u0430\u0446\u0438\u0438 \u0432 \u0446\u0435\u043b\u043e\u043c.<\/p>\n<p>  <\/p>\n<h4 id=\"pochemu-golang\">\u041f\u043e\u0447\u0435\u043c\u0443 Golang?<\/h4>\n<p>  <\/p>\n<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435\u043c\u0438 \u044f\u0437\u044b\u043a\u0430\u043c\u0438, \u0432 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432, \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e, \u0430 \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0438, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0438\u043c\u0435\u044e\u0442 \u043b\u0443\u0447\u0448\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0447\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435. \u041e\u0434\u043d\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0441 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Golang.<\/p>\n<p>  <\/p>\n<h4 id=\"poznakomimsya-s-protobufgrpc\">\u041f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 protobuf\/gRPC<\/h4>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0440\u0430\u043d\u0435\u0435, \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u0434\u043e\u0432\u044b\u0435 \u0431\u0430\u0437\u044b, \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0432\u0430\u0436\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u0432\u044f\u0437\u043d\u044b\u0445 \u0441 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u044c. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043c\u043e\u043d\u043e\u043b\u0438\u0442, \u0442\u043e \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441\u0432\u044f\u0437\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 REST \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u0438\u043b\u0438 XML \u0447\u0435\u0440\u0435\u0437 HTTP. \u041d\u043e \u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0439 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u0410 \u044d\u0442\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435! \u042d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <strong>gRPC<\/strong> \u2014 \u043b\u0451\u0433\u043a\u0438\u0439, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0434\u0432\u043e\u0438\u0447\u043d\u043e\u043c \u043a\u043e\u0434\u0435, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 HTTP, \u0438 \u044d\u0442\u043e \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u043d\u0430\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u0430\u0439\u0442. \u0422\u0430\u043a \u0436\u0435 \u0431\u0443\u0434\u0443\u0449\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTP2 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e \u0441\u043d\u043e\u0432\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 gRPC. HTTP2 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0441\u0442\u0438 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c, \u0438 \u044d\u0442\u043e \u043a\u0440\u0443\u0442\u043e!<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 gRPC \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u0432 \u0434\u0440\u0443\u0436\u0435\u0441\u043a\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u2014 \u044d\u0442\u043e &gt; <strong>protobuf<\/strong>.<\/p>\n<p>  <\/p>\n<h3 id=\"praktika\">\u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0430<\/h3>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \/project\/consigment.proto.<br \/>  <a href=\"https:\/\/developers.google.com\/protocol-buffers\/docs\/gotutorial\">\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f protobuf<\/a><\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">consigment.proto<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>\/\/consigment.proto syntax = &quot;proto3&quot;;  package go.micro.srv.consignment;   service ShippingService {   rpc CreateConsignment(Consignment) returns (Response) {} }  message Consignment {   string id = 1;   string description = 2;   int32 weight = 3;   repeated Container containers = 4;   string vessel_id = 5; }  message Container {   string id = 1;   string customer_id = 2;   string origin = 3;   string user_id = 4; }  message Response {   bool created = 1;   Consignment consignment = 2; }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: service ShippingService, \u0437\u0430\u0442\u0435\u043c \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0441\u0432\u043e\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. Protobuf \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b (\u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432 golang). \u0417\u0434\u0435\u0441\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0432\u043b\u043e\u0436\u0435\u043d \u0432 \u043f\u0430\u0440\u0442\u0438\u044e.<\/p>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0438 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ go get -u google.golang.org\/grpc $ go get -u github.com\/golang\/protobuf\/protoc-gen-go $ sudo apt install protobuf-compiler $ mkdir consignment &amp;&amp; cd consignment $ protoc -I=. --go_out=plugins=grpc:. consignment.proto<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0444\u0430\u0439\u043b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">consignment.pb.go<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ Code generated by protoc-gen-go. DO NOT EDIT. \/\/ source: consignment.proto  package consignment  import (     fmt &quot;fmt&quot;     proto &quot;github.com\/golang\/protobuf\/proto&quot;     context &quot;golang.org\/x\/net\/context&quot;     grpc &quot;google.golang.org\/grpc&quot;     math &quot;math&quot; )  \/\/ Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf  \/\/ This is a compile-time assertion to ensure that this generated file \/\/ is compatible with the proto package it is being compiled against. \/\/ A compilation error at this line likely means your copy of the \/\/ proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 \/\/ please upgrade the proto package  type Consignment struct {     Id                   int32        `protobuf:&quot;varint,1,opt,name=id,proto3&quot; json:&quot;id,omitempty&quot;`     Description          string       `protobuf:&quot;bytes,2,opt,name=description,proto3&quot; json:&quot;description,omitempty&quot;`     Weight               int32        `protobuf:&quot;varint,3,opt,name=weight,proto3&quot; json:&quot;weight,omitempty&quot;`     Containers           []*Container `protobuf:&quot;bytes,4,rep,name=containers,proto3&quot; json:&quot;containers,omitempty&quot;`     VesselId             string       `protobuf:&quot;bytes,5,opt,name=vessel_id,json=vesselId,proto3&quot; json:&quot;vessel_id,omitempty&quot;`     XXX_NoUnkeyedLiteral struct{}     `json:&quot;-&quot;`     XXX_unrecognized     []byte       `json:&quot;-&quot;`     XXX_sizecache        int32        `json:&quot;-&quot;` }  func (m *Consignment) Reset()         { *m = Consignment{} } func (m *Consignment) String() string { return proto.CompactTextString(m) } func (*Consignment) ProtoMessage()    {} func (*Consignment) Descriptor() ([]byte, []int) {     return fileDescriptor_3804bf87090b51a9, []int{0} }  func (m *Consignment) XXX_Unmarshal(b []byte) error {     return xxx_messageInfo_Consignment.Unmarshal(m, b) } func (m *Consignment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {     return xxx_messageInfo_Consignment.Marshal(b, m, deterministic) } func (m *Consignment) XXX_Merge(src proto.Message) {     xxx_messageInfo_Consignment.Merge(m, src) } func (m *Consignment) XXX_Size() int {     return xxx_messageInfo_Consignment.Size(m) } func (m *Consignment) XXX_DiscardUnknown() {     xxx_messageInfo_Consignment.DiscardUnknown(m) }  var xxx_messageInfo_Consignment proto.InternalMessageInfo  func (m *Consignment) GetId() int32 {     if m != nil {         return m.Id     }     return 0 }  func (m *Consignment) GetDescription() string {     if m != nil {         return m.Description     }     return &quot;&quot; }  func (m *Consignment) GetWeight() int32 {     if m != nil {         return m.Weight     }     return 0 }  func (m *Consignment) GetContainers() []*Container {     if m != nil {         return m.Containers     }     return nil }  func (m *Consignment) GetVesselId() string {     if m != nil {         return m.VesselId     }     return &quot;&quot; }  type Container struct {     Id                   int32    `protobuf:&quot;varint,1,opt,name=id,proto3&quot; json:&quot;id,omitempty&quot;`     CustomerId           string   `protobuf:&quot;bytes,2,opt,name=customer_id,json=customerId,proto3&quot; json:&quot;customer_id,omitempty&quot;`     Origin               string   `protobuf:&quot;bytes,3,opt,name=origin,proto3&quot; json:&quot;origin,omitempty&quot;`     UserId               string   `protobuf:&quot;bytes,4,opt,name=user_id,json=userId,proto3&quot; json:&quot;user_id,omitempty&quot;`     XXX_NoUnkeyedLiteral struct{} `json:&quot;-&quot;`     XXX_unrecognized     []byte   `json:&quot;-&quot;`     XXX_sizecache        int32    `json:&quot;-&quot;` }  func (m *Container) Reset()         { *m = Container{} } func (m *Container) String() string { return proto.CompactTextString(m) } func (*Container) ProtoMessage()    {} func (*Container) Descriptor() ([]byte, []int) {     return fileDescriptor_3804bf87090b51a9, []int{1} }  func (m *Container) XXX_Unmarshal(b []byte) error {     return xxx_messageInfo_Container.Unmarshal(m, b) } func (m *Container) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {     return xxx_messageInfo_Container.Marshal(b, m, deterministic) } func (m *Container) XXX_Merge(src proto.Message) {     xxx_messageInfo_Container.Merge(m, src) } func (m *Container) XXX_Size() int {     return xxx_messageInfo_Container.Size(m) } func (m *Container) XXX_DiscardUnknown() {     xxx_messageInfo_Container.DiscardUnknown(m) }  var xxx_messageInfo_Container proto.InternalMessageInfo  func (m *Container) GetId() int32 {     if m != nil {         return m.Id     }     return 0 }  func (m *Container) GetCustomerId() string {     if m != nil {         return m.CustomerId     }     return &quot;&quot; }  func (m *Container) GetOrigin() string {     if m != nil {         return m.Origin     }     return &quot;&quot; }  func (m *Container) GetUserId() string {     if m != nil {         return m.UserId     }     return &quot;&quot; }  type Response struct {     Created              bool         `protobuf:&quot;varint,1,opt,name=created,proto3&quot; json:&quot;created,omitempty&quot;`     Consignment          *Consignment `protobuf:&quot;bytes,2,opt,name=consignment,proto3&quot; json:&quot;consignment,omitempty&quot;`     XXX_NoUnkeyedLiteral struct{}     `json:&quot;-&quot;`     XXX_unrecognized     []byte       `json:&quot;-&quot;`     XXX_sizecache        int32        `json:&quot;-&quot;` }  func (m *Response) Reset()         { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage()    {} func (*Response) Descriptor() ([]byte, []int) {     return fileDescriptor_3804bf87090b51a9, []int{2} }  func (m *Response) XXX_Unmarshal(b []byte) error {     return xxx_messageInfo_Response.Unmarshal(m, b) } func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {     return xxx_messageInfo_Response.Marshal(b, m, deterministic) } func (m *Response) XXX_Merge(src proto.Message) {     xxx_messageInfo_Response.Merge(m, src) } func (m *Response) XXX_Size() int {     return xxx_messageInfo_Response.Size(m) } func (m *Response) XXX_DiscardUnknown() {     xxx_messageInfo_Response.DiscardUnknown(m) }  var xxx_messageInfo_Response proto.InternalMessageInfo  func (m *Response) GetCreated() bool {     if m != nil {         return m.Created     }     return false }  func (m *Response) GetConsignment() *Consignment {     if m != nil {         return m.Consignment     }     return nil }  func init() {     proto.RegisterType((*Consignment)(nil), &quot;Consignment&quot;)     proto.RegisterType((*Container)(nil), &quot;Container&quot;)     proto.RegisterType((*Response)(nil), &quot;Response&quot;) }  func init() { proto.RegisterFile(&quot;consignment.proto&quot;, fileDescriptor_3804bf87090b51a9) }  var fileDescriptor_3804bf87090b51a9 = []byte{     \/\/ 281 bytes of a gzipped FileDescriptorProto     0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0xbf, 0x4e, 0x33, 0x31,     0x10, 0xc4, 0xbf, 0xcb, 0xff, 0x5b, 0x7f, 0x02, 0xc5, 0x05, 0x58, 0x50, 0x70, 0xba, 0x2a, 0xa2,     0x70, 0x11, 0x9e, 0x00, 0xa5, 0x4a, 0xeb, 0xd0, 0xa3, 0x60, 0xaf, 0x2e, 0x2b, 0x11, 0xfb, 0x64,     0x3b, 0xe1, 0x75, 0x78, 0x54, 0x74, 0xbe, 0x1c, 0x18, 0x51, 0xce, 0xac, 0x67, 0xf7, 0xa7, 0x31,     0x2c, 0xb5, 0xb3, 0x81, 0x1a, 0x7b, 0x44, 0x1b, 0x65, 0xeb, 0x5d, 0x74, 0xf5, 0x67, 0x01, 0x6c,     0xf3, 0xe3, 0xf2, 0x2b, 0x18, 0x91, 0x11, 0x45, 0x55, 0xac, 0xa6, 0x6a, 0x44, 0x86, 0x57, 0xc0,     0x0c, 0x06, 0xed, 0xa9, 0x8d, 0xe4, 0xac, 0x18, 0x55, 0xc5, 0xaa, 0x54, 0xb9, 0xc5, 0x6f, 0x60,     0xf6, 0x81, 0xd4, 0x1c, 0xa2, 0x18, 0xa7, 0xd4, 0x45, 0xf1, 0x47, 0x00, 0xed, 0x6c, 0xdc, 0x93,     0x45, 0x1f, 0xc4, 0xa4, 0x1a, 0xaf, 0xd8, 0x1a, 0xe4, 0x66, 0xb0, 0x54, 0x36, 0xe5, 0xf7, 0x50,     0x9e, 0x31, 0x04, 0x7c, 0x7f, 0x25, 0x23, 0xa6, 0xe9, 0xc6, 0xa2, 0x37, 0xb6, 0xa6, 0x3e, 0x42,     0xf9, 0x9d, 0xfa, 0xc3, 0xf7, 0x00, 0x4c, 0x9f, 0x42, 0x74, 0x47, 0xf4, 0x5d, 0xb6, 0xe7, 0x83,     0xc1, 0xda, 0x9a, 0x0e, 0xcf, 0x79, 0x6a, 0xc8, 0x26, 0xbc, 0x52, 0x5d, 0x14, 0xbf, 0x85, 0xf9,     0x29, 0xf4, 0xa1, 0x49, 0x3f, 0xe8, 0xe4, 0xd6, 0xd4, 0x2f, 0xb0, 0x50, 0x18, 0x5a, 0x67, 0x03,     0x72, 0x01, 0x73, 0xed, 0x71, 0x1f, 0xb1, 0x3f, 0xb9, 0x50, 0x83, 0xe4, 0x12, 0x58, 0x56, 0x66,     0xba, 0xcb, 0xd6, 0xff, 0x65, 0x56, 0xa5, 0xca, 0x1f, 0xac, 0x9f, 0xe1, 0x7a, 0x77, 0xa0, 0xb6,     0x25, 0xdb, 0xec, 0xd0, 0x9f, 0x49, 0x23, 0x97, 0xb0, 0xdc, 0xa4, 0x6d, 0x79, 0xff, 0xbf, 0x56,     0xdc, 0x95, 0x72, 0x40, 0xa9, 0xff, 0xbd, 0xcd, 0xd2, 0x8f, 0x3d, 0x7d, 0x05, 0x00, 0x00, 0xff,     0xff, 0x84, 0x5c, 0xa4, 0x06, 0xc6, 0x01, 0x00, 0x00, }  \/\/ Reference imports to suppress errors if they are not otherwise used. var _ context.Context var _ grpc.ClientConn  \/\/ This is a compile-time assertion to ensure that this generated file \/\/ is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion4  \/\/ ShippingServiceClient is the client API for ShippingService service. \/\/ \/\/ For semantics around ctx use and closing\/ending streaming RPCs, please refer to https:\/\/godoc.org\/google.golang.org\/grpc#ClientConn.NewStream. type ShippingServiceClient interface {     CreateConsignment(ctx context.Context, in *Consignment, opts ...grpc.CallOption) (*Response, error) }  type shippingServiceClient struct {     cc *grpc.ClientConn }  func NewShippingServiceClient(cc *grpc.ClientConn) ShippingServiceClient {     return &amp;shippingServiceClient{cc} }  func (c *shippingServiceClient) CreateConsignment(ctx context.Context, in *Consignment, opts ...grpc.CallOption) (*Response, error) {     out := new(Response)     err := c.cc.Invoke(ctx, &quot;\/ShippingService\/CreateConsignment&quot;, in, out, opts...)     if err != nil {         return nil, err     }     return out, nil }  \/\/ ShippingServiceServer is the server API for ShippingService service. type ShippingServiceServer interface {     CreateConsignment(context.Context, *Consignment) (*Response, error) }  func RegisterShippingServiceServer(s *grpc.Server, srv ShippingServiceServer) {     s.RegisterService(&amp;_ShippingService_serviceDesc, srv) }  func _ShippingService_CreateConsignment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {     in := new(Consignment)     if err := dec(in); err != nil {         return nil, err     }     if interceptor == nil {         return srv.(ShippingServiceServer).CreateConsignment(ctx, in)     }     info := &amp;grpc.UnaryServerInfo{         Server:     srv,         FullMethod: &quot;\/ShippingService\/CreateConsignment&quot;,     }     handler := func(ctx context.Context, req interface{}) (interface{}, error) {         return srv.(ShippingServiceServer).CreateConsignment(ctx, req.(*Consignment))     }     return interceptor(ctx, in, info, handler) }  var _ShippingService_serviceDesc = grpc.ServiceDesc{     ServiceName: &quot;ShippingService&quot;,     HandlerType: (*ShippingServiceServer)(nil),     Methods: []grpc.MethodDesc{         {             MethodName: &quot;CreateConsignment&quot;,             Handler:    _ShippingService_CreateConsignment_Handler,         },     },     Streams:  []grpc.StreamDesc{},     Metadata: &quot;consignment.proto&quot;, }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438, \u0447\u0442\u043e \u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b -I \u043f\u0443\u0442\u044c \u0433\u0434\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0438\u0449\u0435\u0442 \u0444\u0430\u043b\u0439\u043b\u044b, &#8212;go_out \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b. \u0412\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u043f\u0440\u0430\u0432\u043a\u0430 <\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ protoc -h <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 gRPC \/ protobuf, \u0447\u0442\u043e\u0431\u044b \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 protobuf \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>  <\/p>\n<h4 id=\"napishem-maingo\">\u041d\u0430\u043f\u0438\u0448\u0435\u043c main.go<\/h4>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">main.go<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package seaport  import (     &quot;log&quot;     &quot;net&quot;      \/\/ \u0418\u043c\u043f\u043e\u0442\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434 \u043f\u0440\u043e\u0442\u043e\u0431\u0443\u0444\u0435\u0440\u0430     pbf &quot;seaport\/consignment&quot;      &quot;golang.org\/x\/net\/context&quot;     &quot;google.golang.org\/grpc&quot;     &quot;google.golang.org\/grpc\/reflection&quot;  )  const (     port = &quot;:50051&quot; )  \/\/IRepository - \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 type IRepository interface {     Create(*pbf.Consignment) (*pbf.Consignment, error) }  \/\/ Repository - \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u044d\u043c\u0438\u0442\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \/\/ \u043f\u043e\u0441\u043b\u0435 \u043c\u044b \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0435\u0451 \u043d\u0430 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c type Repository struct {     consignments []*pbf.Consignment }  \/\/Create - \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 func (repo *Repository) Create(consignment *pbf.Consignment) (*pbf.Consignment, error) {     updated := append(repo.consignments, consignment)     repo.consignments = updated     return consignment, nil }  \/\/ \u0421\u043b\u0443\u0436\u0431\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \/\/ \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u0431\u0443\u0444\u0430. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \/\/ \u0432 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u044b\u0445 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0442. \u0434. type service struct {     repo IRepository }  \/\/ CreateConsignment - \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \/\/ \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c create, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \/\/ \u043f\u043e\u0442\u043e\u043c \u043e\u043d\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c gRPC. func (s *service) CreateConsignment(ctx context.Context, req *pbf.Consignment) (*pbf.Response, error) {      \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u043d\u0430\u0448\u0443 \u043f\u0430\u0440\u0442\u0438\u044e \u0432 \u0445\u0440\u0430\u043d\u0438\u0434\u0438\u0449\u0435     consignment, err := s.repo.Create(req)     if err != nil {         return nil, err     }      \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 `Response`,     \/\/ \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u043d\u0438\u0438 \u043f\u0440\u043e\u0431\u0443\u0444\u0430     return &amp;pbf.Response{Created: true, Consignment: consignment}, nil }  func main() {      repo := &amp;Repository{}      \/\/ \u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u043d\u0430\u0448 gRPC \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u043d\u0438\u044f tcp     lis, err := net.Listen(&quot;tcp&quot;, port)     if err != nil {         log.Fatalf(&quot;failed to listen: %v&quot;, err)     }     s := grpc.NewServer()      \/\/ \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u043d\u0430\u0448\u0443 \u0441\u043b\u0443\u0436\u0431\u0443 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 gRPC, \u044d\u0442\u043e \u0441\u0432\u044f\u0436\u0435\u0442 \u043d\u0430\u0448\u0443     \/\/ \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e     \/\/ \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f `Response`, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0442\u043e\u0431\u0443\u0444\u0435     pbf.RegisterShippingServiceServer(s, &amp;service{repo})      \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0441\u043b\u0443\u0436\u0431\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 gRPC.     reflection.Register(s)     if err := s.Serve(lis); err != nil {         log.Fatalf(&quot;failed to serve: %v&quot;, err)     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u043a\u043e\u0434\u0435. \u0421\u0443\u0434\u044f \u043f\u043e \u0432\u0441\u0435\u043c\u0443, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b gRPC \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 gRPC \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 50051. \u0422\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0436\u0438\u0442\u044c \u043d\u0430\u0448 gRPC \u0441\u0435\u0440\u0432\u0438\u0441.<br \/>  \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>$ go run main.go<\/strong>, \u043d\u043e \u0432\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435, \u0438 \u0432\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u2026 \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u044c\u043c\u0435\u0442 \u0444\u0430\u0439\u043b JSON \u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0435\u0439 \u0441\u043b\u0443\u0436\u0431\u043e\u0439 gRPC.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433 <strong>$ mkdir consignment-cli<\/strong>. \u0412 \u044d\u0442\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0444\u0430\u0439\u043b cli.go \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">cli.go<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package main  import (     &quot;encoding\/json&quot;     &quot;io\/ioutil&quot;     &quot;log&quot;     &quot;os&quot;      pbf &quot;seaport\/consignment&quot;      &quot;golang.org\/x\/net\/context&quot;     &quot;google.golang.org\/grpc&quot; )  const (     address         = &quot;localhost:50051&quot;     defaultFilename = &quot;consignment.json&quot; )  \/\/\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0438\u043b func parseFile(file string) (*pbf.Consignment, error) {     var consignment *pbf.Consignment     data, err := ioutil.ReadFile(file)     if err != nil {         return nil, err     }     json.Unmarshal(data, &amp;consignment)     return consignment, err }  func main() {     \/\/ \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c     conn, err := grpc.Dial(address, grpc.WithInsecure())     if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f: %v&quot;, err)     }     defer conn.Close()     client := pbf.NewShippingServiceClient(conn)      \/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 consignment.json,     \/\/ \u0438\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438     file := defaultFilename     if len(os.Args) &gt; 1 {         file = os.Args[1]     }      consignment, err := parseFile(file)      if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0444\u0430\u0438\u043b: %v&quot;, err)     }      r, err := client.CreateConsignment(context.Background(), consignment)     if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c: %v&quot;, err)     }     log.Printf(&quot;\u0421\u043e\u0437\u0434\u0430\u043d: %t&quot;, r.Created)  }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043f\u0430\u0440\u0442\u0438\u044e (consignment-cli \/ consignment.json):<\/p>\n<p>  <\/p>\n<pre><code>{   &quot;description&quot;: &quot;\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0430\u0440\u0442\u0438\u044f \u0433\u0440\u0443\u0437\u0430&quot;,   &quot;weight&quot;: 100,   &quot;containers&quot;: [     {       &quot;customer_id&quot;: &quot;\u0417\u0430\u043a\u0430\u0437\u0447\u0438\u043a_001&quot;,       &quot;user_id&quot;: &quot;\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c_001&quot;,       &quot;origin&quot;: &quot;\u041f\u043e\u0440\u0442 \u041d\u0430\u0445\u043e\u0434\u043a\u0430&quot;     }   ],   &quot;vessel_id&quot;: &quot;\u0441\u0443\u0434\u043d\u043e_001&quot; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <strong>$ go run main.go<\/strong> \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 seaport, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <strong>$ go run cli.go<\/strong>. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u00abCreated: true\u00bb.<br \/>  \u041d\u043e \u043a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043e? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448\u0443 \u0441\u043b\u0443\u0436\u0431\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 GetConsignments, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0442\u0438\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">consigment.proto<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/consigment.proto syntax = &quot;proto3&quot;;  service ShippingService{   rpc CreateConsignment(Consignment) returns (Response) {}    \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434   rpc GetConsignments(GetRequest) returns (Response) {} }  message Consignment {   int32 id = 1;   string description = 2;   int32 weight = 3;   repeated Container containers = 4;   string vessel_id = 5; }  message Container {   int32 id =1;   string customer_id =2;   string origin = 3;   string user_id = 4; }  \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 message GetRequest {}  message Response {   bool created = 1;   Consignment consignment = 2;    \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u044e\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0442\u0438\u0439   \/\/ \u0432 \u043d\u0430\u0448\u0435 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435   repeated Consignment consignments = 3; }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <strong>GetConsignments<\/strong>, \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 <strong>GetRequest<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0438\u0447\u0435\u0433\u043e. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0439 \u0432 \u043d\u0430\u0448\u0435 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. \u0412\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u0442\u0438\u043f \u0437\u0434\u0435\u0441\u044c \u0438\u043c\u0435\u0435\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e repeated \u0434\u043e \u0442\u0438\u043f\u0430. \u042d\u0442\u043e, \u043a\u0430\u043a \u0432\u044b, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0438\u0441\u044c, \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u043a\u0430\u043a \u043c\u0430\u0441\u0441\u0438\u0432 \u044d\u0442\u0438\u0445 \u0442\u0438\u043f\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041d\u0435 \u0441\u043f\u0435\u0448\u0438\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 gRPC \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 protobuf, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0448\u0435\u043c\u0443 proto \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/seaport\/main.go  \/\/IRepository - \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 type IRepository interface {     Create(*pbf.Consignment) (*pbf.Consignment, error)     GetAll() []*pbf.Consignment }  \/\/GetAll - \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0442\u0438\u0439 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 func (repo *Repository) GetAll() []*pbf.Consignment {     return repo.consignments }  \/\/GetConsignments - \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0442\u0438\u0439 \u0438\u0437 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 func (s *service) GetConsignments(ctx context.Context, req *pbf.GetRequest) (*pbf.Response, error) {     consignments := s.repo.GetAll()     return &amp;pbf.Response{Consignments: consignments}, nil }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u043d\u0430\u0448 \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 GetConsignments, \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0438 \u043d\u0430\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0442\u043e. \u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <strong>$ go run main.go<\/strong>, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043d\u043e\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 cli, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u043d\u0430\u0448\u0438 \u043f\u0430\u0440\u0442\u0438\u0438:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">cli.go<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package main  import (     &quot;encoding\/json&quot;     &quot;io\/ioutil&quot;     &quot;log&quot;     &quot;os&quot;      pbf &quot;seaport\/consignment&quot;      &quot;golang.org\/x\/net\/context&quot;     &quot;google.golang.org\/grpc&quot; )  const (     address         = &quot;localhost:50051&quot;     defaultFilename = &quot;consignment.json&quot; )  \/\/\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0438\u043b func parseFile(file string) (*pbf.Consignment, error) {     var consignment *pbf.Consignment     data, err := ioutil.ReadFile(file)     if err != nil {         return nil, err     }     json.Unmarshal(data, &amp;consignment)     return consignment, err }  func main() {     \/\/ \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c     conn, err := grpc.Dial(address, grpc.WithInsecure())     if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u043c\u043e\u0433\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f: %v&quot;, err)     }     defer conn.Close()     client := pbf.NewShippingServiceClient(conn)      \/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 consignment.json,     \/\/ \u0438\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438     file := defaultFilename     if len(os.Args) &gt; 1 {         file = os.Args[1]     }      consignment, err := parseFile(file)      if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0444\u0430\u0438\u043b: %v&quot;, err)     }      r, err := client.CreateConsignment(context.Background(), consignment)     if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c: %v&quot;, err)     }     log.Printf(&quot;\u0421\u043e\u0437\u0434\u0430\u043d: %t&quot;, r.Created)      getAll, err := client.GetConsignments(context.Background(), &amp;pbf.GetRequest{})     if err != nil {         log.Fatalf(&quot;\u041d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u0440\u0442\u0438\u0439: %v&quot;, err)     }     for _, v := range getAll.Consignments {         log.Println(v)     }  }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u043e\u0434 \u0432\u044b\u0448\u0435 \u0432 cli.go \u0438 \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <strong>$ go run cli.go<\/strong>. \u041a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 CreateConsignment, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u043e\u0432\u0435\u0442 GetConsignments. \u0418 \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043e\u0441\u0442\u0430\u0432 \u043f\u0430\u0440\u0442\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0443 \u043d\u0430\u0441 \u043f\u0435\u0440\u0432\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0438\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f protobuf \u0438 gRPC.<\/p>\n<p>  <\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u044d\u0442\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e go-micro, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u043e\u0449\u043d\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 gRPC. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448 \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u043d\u0430\u0448 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0438 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445 Docker \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u044d\u0442\u043e\u0439 \u0441\u0435\u0440\u0438\u0438.<\/p>\n<\/div>\n<p>        <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/post\/425653\/\"> https:\/\/habr.com\/post\/425653\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\n<h3 id=\"vvedenie-v-mikroservisnuyu-arhitekturu\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443<\/h3>\n<p>  <\/p>\n<h4 id=\"chast-1-iz-10\">\u0427\u0430\u0441\u0442\u044c 1 \u0438\u0437 10<\/h4>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0441\u0435\u0440\u0438\u044f \u0438\u0437 \u0434\u0435\u0441\u044f\u0442\u0438 \u0447\u0430\u0441\u0442\u0435\u0439, \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0437 \u0432 \u043c\u0435\u0441\u044f\u0446 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Golang. \u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c protobuf \u0438 gRPC \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. <\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b: golang, mongodb, grpc, docker, Google Cloud, Kubernetes, NATS, CircleCI, Terraform \u0438 go-micro.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u043c\u043d\u0435 \u044d\u0442\u043e? \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430\u043a\u043e\u043f\u0438\u0432\u0448\u0438\u0435\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0422\u0430\u043a \u0436\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0442\u0435\u043c, \u0447\u0442\u043e \u044f \u0443\u0437\u043d\u0430\u043b \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 Go \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u043e\u0432\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0433\u0440\u0443\u0437\u044b<\/li>\n<li>\u0438\u043d\u0432\u0435\u043d\u0442\u0430\u0440\u044c<\/li>\n<li>\u0441\u0443\u0434\u0430<\/li>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438<\/li>\n<li>\u0440\u043e\u043b\u0438<\/li>\n<li>\u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/fg\/di\/ez\/fgdiezxwlpd1eghakcgbkgfi3yu.jpeg\" alt=\"image\"\/><\/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-290459","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/290459","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=290459"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/290459\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=290459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=290459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=290459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}