-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 42.6 KB
/
content.json
1
{"meta":{"title":"40PK Channel","subtitle":null,"description":"Подборка интересных материалов из мира программирования.","author":"Ilya Perkovec","url":"http://40pk.github.io"},"pages":[{"title":"Категории","date":"2018-08-14T11:23:58.492Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"categories/index.html","permalink":"http://40pk.github.io/categories/index.html","excerpt":"","text":""},{"title":"О 40PK","date":"2018-08-14T11:23:58.504Z","updated":"2018-08-14T11:23:58.504Z","comments":true,"path":"info/index.html","permalink":"http://40pk.github.io/info/index.html","excerpt":"","text":"40PK Channel - это сайт и канал в Телеграм, где для вас находят и публикуют самые интересные материалы и мероприятия из мира программирования. Наш канал в телеграмме — @fortypkE-mail — fortypk@gmail.com"},{"title":"Теги","date":"2018-08-14T11:23:58.504Z","updated":"2018-08-14T11:23:58.504Z","comments":true,"path":"tags/index.html","permalink":"http://40pk.github.io/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"1.2. PROграммист. Структуры данных - Queue (очередь)","slug":"2-PROграммист-Структуры-данных-Queue-очередь","date":"2018-08-14T10:46:33.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/08/14/2-PROграммист-Структуры-данных-Queue-очередь/","link":"","permalink":"http://40pk.github.io/2018/08/14/2-PROграммист-Структуры-данных-Queue-очередь/","excerpt":"В прошлой статье мы рассматривали такую структуру данных, как стек. Сейчас рассмотрим нечто подобное под названием Queue (очередь).","text":"В прошлой статье мы рассматривали такую структуру данных, как стек. Сейчас рассмотрим нечто подобное под названием Queue (очередь).Главное отличие очереди от стека - мы забираем тот элемент, который был в “начале”. Просто представь обычную очередь в кассе, первым обслуживается тот покупатель, что первым подошёл к кассе, а затем обслуживаются все последующие покупатели в порядке “занятых мест”. Основные операции enqueue() и dequeue() аналогичны операциям push() и pop() в стеке, соответственно. А сейчас опять гифка с принципом работы очереди. Теперь давай реализуем очередь, чтобы опробовать его на практике и понять как он работает. Мне приглянулся способ на двух стеках (код для стека используем с прошлой статьи): 123456789101112131415161718192021222324252627// Конструктор Queuefunction Queue() { this._stack1 = new Stack(); this._stack2 = new Stack();}// Функция enqueue добавляет элемент в очередьQueue.prototype.enqueue = function enqueue(element) { this._stack1.push(element);};// Функция dequeue удаляет и возвращает элемент в начале очередиQueue.prototype.dequeue = function dequeue() { if (!this._stack2.length) { if (!this._stack1.length) { return null; } // В цикле мы переносим элементы из первого стека, во второй, тем самым его \"переворачивая\", вспомните как работает стек while (this._stack1.length) { this._stack2.push(this._stack1.pop()); } } // Возвращаем и удаляем \"верхний\" элемент второго стека, ведь он у нас перевернутый и каждый верхний элемент стека является элементом в начале нашей очереди return this._stack2.pop();}; Если не хочешь использовать велосипед, то в JavaScript массивах есть функции push() и shift(), аналогичны операциям enqueue() и dequeue() в очередях. Ну а сейчас посмотрим как работает наш вариант очереди: 12345678910111213var queue = new Queue();queue.enqueue(5);queue.enqueue(3);queue.enqueue(8);console.log(queue.dequeue()); // Возвращает 5console.log(queue.dequeue()); // Возвращает 3queue.enqueue(2);console.log(queue.dequeue()); // Возвращает 8console.log(queue.dequeue()); // Возвращает 2 Работает! На этом все, спасибо, что дочитал до конца, возможно, узнал что-то новое.","categories":[{"name":"Статьи","slug":"Статьи","permalink":"http://40pk.github.io/categories/Статьи/"}],"tags":[{"name":"PROграммист","slug":"PROграммист","permalink":"http://40pk.github.io/tags/PROграммист/"},{"name":"JavaScript","slug":"JavaScript","permalink":"http://40pk.github.io/tags/JavaScript/"},{"name":"Структуры данных","slug":"Структуры-данных","permalink":"http://40pk.github.io/tags/Структуры-данных/"},{"name":"Queue","slug":"Queue","permalink":"http://40pk.github.io/tags/Queue/"},{"name":"Очередь","slug":"Очередь","permalink":"http://40pk.github.io/tags/Очередь/"}]},{"title":"1.1. PROграммист. Структуры данных - Stack (стек)","slug":"1-PROграммист-Структуры-данных-Stack-стек","date":"2018-08-07T08:33:58.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/08/07/1-PROграммист-Структуры-данных-Stack-стек/","link":"","permalink":"http://40pk.github.io/2018/08/07/1-PROграммист-Структуры-данных-Stack-стек/","excerpt":"ДебютЭта статья является отправной точкой целой серии статей “PROграммист”, в которых я буду объяснять различные аспекты программирования, простым языком, без формальностей. Надеюсь мои труды не пропадут зря и помогут кому-то стать реальным PRO!","text":"ДебютЭта статья является отправной точкой целой серии статей “PROграммист”, в которых я буду объяснять различные аспекты программирования, простым языком, без формальностей. Надеюсь мои труды не пропадут зря и помогут кому-то стать реальным PRO! Поехали!Начнём со структур данных, а точнее со Stack (стек). Из названия понятно, что он представляет из себя “стопку”, где забираешь тот предмет, который положил последним в стопку. Мне не нравятся примеры с книгами и тарелками, где вот есть стопка книг/тарелок, первым ты возьмёшь ту, что сверху, которую положил последней. Плохой пример, ведь можно включить зануду и сказать “ха, так я могу приподнять первые n книг/тарелок и взять с середины”, поэтому я больше люблю аналогию с магазином автомата, как по мне эталонный стек, зарядил патрон, ты его и выстрелишь первым, и никаких там “взять с середины”. Для стека используются две основные операции - push и pop. Push - добавить элемент в стек, pop - удаляем элемент из стека. Проще простого! Чтобы проще было понять, держи гифку о том, как это все работает, хотя тут и так всё проще простого. Теперь создадим стек в JavaScript:123456789101112131415161718192021222324252627282930313233// Конструктор Stackfunction Stack() { this.length = 0; // хранит длинну стека this._elements = {}; // хранит элементы стека в необходимом порядке}// Функция push добавляет элемент в стекStack.prototype.push = function push(element) { var length = ++this.length; this._elements[length] = element;}; // Функция pop удаляет и вовращает последний добавленный элемент стекаStack.prototype.pop = function pop() { var length = this.length; var deletedData; // Эту переменную используем для хранения \"верхнего\" элемента стека перед удалением, чтобы потом вернуть его if (length > 0) { // Проверяем, не пустой ли стек, ведь что можно взять с пустого стека deletedData = this._elements[length]; delete this._elements[length]; --this.length; return deletedData; } return null;};// Функция peek возвращает \"верхний\" элемент стека без его удаленияStack.prototype.peek = function peek() { return this._elements[this.length];}; Конечно ты можешь возмутиться “что за треш, у массивов в JS и без того есть функции push() и pop(), чтобы работать как со стеком”, но ведь задача показать именно принцип работы стека. И как видно из кода, тут добавилась ещё одна операция peek(), которая по сути выполняет то же самое, что и pop(), но без удаления элемента. Пример использования:1234567891011var stack = new Stack();stack.push(5);stack.push(8);stack.push(9);console.log(stack.pop()); // Вывод: 9console.log(stack.peek()); // Вывод: 8console.log(stack.pop()); // Вывод: 8, потому что операция peek не удаляет элементconsole.log(stack.pop()); // Вывод: 5console.log(stack.pop()); // Вывод: null, потому что стек пуст На этом думаю всё, дальше продолжим говорить про структуры данных. Надеюсь тебе понравилось, %USERNAME%.","categories":[{"name":"Статьи","slug":"Статьи","permalink":"http://40pk.github.io/categories/Статьи/"}],"tags":[{"name":"PROграммист","slug":"PROграммист","permalink":"http://40pk.github.io/tags/PROграммист/"},{"name":"JavaScript","slug":"JavaScript","permalink":"http://40pk.github.io/tags/JavaScript/"},{"name":"Структуры данных","slug":"Структуры-данных","permalink":"http://40pk.github.io/tags/Структуры-данных/"},{"name":"Stack","slug":"Stack","permalink":"http://40pk.github.io/tags/Stack/"},{"name":"Стек","slug":"Стек","permalink":"http://40pk.github.io/tags/Стек/"}]},{"title":"Wired Elements","slug":"Wired-Elements","date":"2018-05-30T14:45:56.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/05/30/Wired-Elements/","link":"","permalink":"http://40pk.github.io/2018/05/30/Wired-Elements/","excerpt":"Wired Elements - это набор основных элементов пользовательского интерфейса, которые имеют рисованный вид. Они могут быть использованы для каркасов, макетов или просто повесилиться с внешним видом ручной работы.","text":"Wired Elements - это набор основных элементов пользовательского интерфейса, которые имеют рисованный вид. Они могут быть использованы для каркасов, макетов или просто повесилиться с внешним видом ручной работы.Элементы рисуются рандомно так, что две визуализации не будут одинаковыми - как две отдельно нарисованные фигуры. Проект доступен на GitHub.","categories":[{"name":"Проекты","slug":"Проекты","permalink":"http://40pk.github.io/categories/Проекты/"}],"tags":[{"name":"UI","slug":"UI","permalink":"http://40pk.github.io/tags/UI/"},{"name":"ReactJS","slug":"ReactJS","permalink":"http://40pk.github.io/tags/ReactJS/"}]},{"title":"Vuido","slug":"Vuido","date":"2018-05-27T16:17:34.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/05/27/Vuido/","link":"","permalink":"http://40pk.github.io/2018/05/27/Vuido/","excerpt":"Vuido позволяет создавать нативные приложения с использованием Vue.js. Приложение, использующее Vuido, может работать в Windows, OS X и Linux, используя нативные компоненты GUI и не требует использования Electron.","text":"Vuido позволяет создавать нативные приложения с использованием Vue.js. Приложение, использующее Vuido, может работать в Windows, OS X и Linux, используя нативные компоненты GUI и не требует использования Electron.Под капотом Vuido использует библиотеку libui, которая предоставляет нативные GUI компоненты для каждой платформы и libui-node для работы с библиотекой в Node.js. Проект доступен на GitHub.","categories":[{"name":"Проекты","slug":"Проекты","permalink":"http://40pk.github.io/categories/Проекты/"}],"tags":[{"name":"OSX","slug":"OSX","permalink":"http://40pk.github.io/tags/OSX/"},{"name":"Linux","slug":"Linux","permalink":"http://40pk.github.io/tags/Linux/"},{"name":"Windows","slug":"Windows","permalink":"http://40pk.github.io/tags/Windows/"},{"name":"VueJS","slug":"VueJS","permalink":"http://40pk.github.io/tags/VueJS/"},{"name":"NodeJS","slug":"NodeJS","permalink":"http://40pk.github.io/tags/NodeJS/"},{"name":"libui","slug":"libui","permalink":"http://40pk.github.io/tags/libui/"}]},{"title":"ClassicKit","slug":"ClassicKit","date":"2018-05-16T14:41:51.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/05/16/ClassicKit/","link":"","permalink":"http://40pk.github.io/2018/05/16/ClassicKit/","excerpt":"Набор UI компонентов для UIKit в стиле Windows 95.","text":"Набор UI компонентов для UIKit в стиле Windows 95. Проект доступен на GitHub.","categories":[{"name":"Проекты","slug":"Проекты","permalink":"http://40pk.github.io/categories/Проекты/"}],"tags":[{"name":"iOS","slug":"iOS","permalink":"http://40pk.github.io/tags/iOS/"},{"name":"UIKit","slug":"UIKit","permalink":"http://40pk.github.io/tags/UIKit/"}]},{"title":"11 лучших шрифтов для программирования","slug":"11-лучших-шрифтов-для-программирования","date":"2018-05-16T10:27:14.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/05/16/11-лучших-шрифтов-для-программирования/","link":"","permalink":"http://40pk.github.io/2018/05/16/11-лучших-шрифтов-для-программирования/","excerpt":"Есть много статей и сайтов, сравнивающих шрифты для программирования, и все они замечательны. Так почему же я повторяю ту же тему здесь? Я всегда терял среди десятков шрифтов и не мог решить, какой из них для меня лучше.","text":"Есть много статей и сайтов, сравнивающих шрифты для программирования, и все они замечательны. Так почему же я повторяю ту же тему здесь? Я всегда терял среди десятков шрифтов и не мог решить, какой из них для меня лучше.Поскольку я всегда находил себя потерянным в десятках шрифтов и не мог понять, какой из них лучше для меня. Поэтому сегодня я попробовал много шрифтов и сделал подборку для вас. Эти шрифты довольно популярны и легкодоступны. И самое главное, все эти шрифты БЕСПЛАТНЫ! Я оцениваю шрифты по следующим показателям: Являются ли похожие символы различаемыми, например, 0O, 1lI Является ли стиль шрифта (ширина строки, ширина/высота символа) легко читаемым. И мои личные предпочтения! Скриншоты сделаны В VSCode с одним и тем же фрагментом кода. На всех скриншотах используется одинаковый параметр настроек редактора "editor.fontSize": 14. 1. HackHack это открытый шрифт, специально созданный для кожа и основанный на проектах Bitstream Vera и DejaVu. 0O и 1lI четко различимы, а шрифт легко читается. Особенно мне нравится ноль с чертой в центре. 2. DejaVu Sans MonoОснованный на Bitstream Vera, DejaVu также является отличным бесплатным шрифтом с лицензией. Sans Mono четко выделяет 0O и 1lI. Точка внутри 0 меньше по сравнению с Hack, но в целом этот шрифт удобен. 3. MonacoМонако - это шрифт по умолчанию в системе OSX до версии Snow Leopard. Сииволы отличаются друг от друга, поэтому трудно перепутать 0O и 1lI. Мне нравится этот шрифт из-за его особого стиля, который заставляет меня чувствовать себя снова пользователем OSX (в основном, сейчас использую Ubuntu). 4. Source Code ProSource Code Pro разработан компанией Adobe. В целом текст выглядит более четким, чем в других шрифтах, не говоря уже о разборчивости символов. 5. MenloMenlo - это новый стандартны шрифт в macOS для программ Xcode и Terminal. Он основан на DejaVu Sans Mono. Лично мне больше нравится Monaco, потому что я использовал OSX давным-давно, но Menlo тоже хороший выбор для программирования. UPD: Menlo больше не шрифт по умолчанию в macOS. В macOS High Sierra шрифт по умолчанию был изменен на San Francisco Mono, который тоже является отличным выбором для программирования 6. ConsolasConsolas является шрифтом по умолчанию для Microsoft Visual Studio. Он очень популярен, потому что он поставляется с Windows. Лично мне не очень нравится символ l, так как его легко путать с 1. 7. Space MonoSpace Mono разработан Colophon Foundry и представляет собой отличный моноширинный шрифт. Два минуса, которые мне не нравятся: l можно спутать с 1 , не отличается от . при размере шрифта в 14pt. 8. FiraCodeFiraCode поддерживает функцию лигирования шрифтов. Он может объединить два или более символов в один символ, чтобы сделать чтение кода более понятным. Обратите внимание на ! =, <=, и == на скриншоте ниже. Хотя мне не нравится лигатура, потому меня немного смущает, когда вижу слияние символов, но я считаю, что этот шрифт поможет другим людям. Примечание: в VSCode в настройках необходимо добавить следующую строку, чтобы включить лигатуру шрифта. 1"editor.fontLigatures": true 9. Anonymous ProМне нравится Anonymous Pro, потому что он дает ощущение печатной машинки. Кроме того, символ < уже, чем в Hack, что делает его более похожим на символ. 10. IBM 3270IBM 3270 основан на шрифте, используемом в одноименном терминале, разработанном IBM в 1971 году. Этот шрифт отлично подходит для программирования и придает коду ретро-стиль (хотя я не совсем привык к нему). Обратите внимание, что этот шрифт относительно мал, поэтому я предлогаю увеличить размер шрифта и уменьшить высоту строки, чтобы сделать его более читабельным. 12"editor.lineHeight": 20,"editor.fontSize": 14, 11. Droid Sans MonoDroid Sans был создан для Android и это достаточно красивый шрифт. Однако самая большая проблема заключается в том, что он не имеет нуля, поэтому 0 и O не различаются. Спасибо за прочтение! Надеюсь, эта статья поможет вам найти новый шрифт для вашей IDE или терминала. Источник: itnext.io","categories":[{"name":"Статьи","slug":"Статьи","permalink":"http://40pk.github.io/categories/Статьи/"}],"tags":[{"name":"Типографика","slug":"Типографика","permalink":"http://40pk.github.io/tags/Типографика/"},{"name":"Шрифт","slug":"Шрифт","permalink":"http://40pk.github.io/tags/Шрифт/"},{"name":"Программирование","slug":"Программирование","permalink":"http://40pk.github.io/tags/Программирование/"},{"name":"Перевод","slug":"Перевод","permalink":"http://40pk.github.io/tags/Перевод/"}]},{"title":"Как сделать поисковой микросервис","slug":"Как-сделать-поисковой-микросервис","date":"2018-05-14T19:50:57.000Z","updated":"2018-08-14T11:23:58.492Z","comments":true,"path":"2018/05/14/Как-сделать-поисковой-микросервис/","link":"","permalink":"http://40pk.github.io/2018/05/14/Как-сделать-поисковой-микросервис/","excerpt":"Поиск является неотъемлемой частью любого приложения и возможность найти что-либо через строку поиска. Есть много способов сделать это, я видел как это сделано на стороне клиента с помощью цикла, или же с полнотекстовой индексацией в Postgres или MySQL. Но наступает ситуация, где нам нужен отдельный поисковой сервис, и для этого часто выбирают Elasticsearch.","text":"Поиск является неотъемлемой частью любого приложения и возможность найти что-либо через строку поиска. Есть много способов сделать это, я видел как это сделано на стороне клиента с помощью цикла, или же с полнотекстовой индексацией в Postgres или MySQL. Но наступает ситуация, где нам нужен отдельный поисковой сервис, и для этого часто выбирают Elasticsearch.В этой статье я покажу как сделать простой поисковой микросервис, используя язык программирования Golang. Мы будем искать пользователей по электронной почте, никнейму и настоящему имени. Все исходники вы можете найти на GitHub. АрхитектураПрежде чем начать писать код давайте разберемся как это должно работать. Важно понимать, что Elasticsearch не должен подвергаться прямому воздействию клиента, поэтому создание промежуточного микросервиса имеет важное значение. В этом примере для микросервиса потребуется один endpoint для поиска. Также нам надо заполнить кеш Elasticsearch’а, поэтому нам понадобится второй endpoint. В реальном приложении лучше использовать какую-то очередь для набора Producer и Consumer (подробнее об этом описано здесь), чтобы заполнить систему. Однако мы не будем к этому прибегать в этой статье. Мы будем использовать в качестве двух endpoint’ов следующее: /search /populate Эти endpoint’ы будут получать параметры. ПоискПоисковой endpoint должен получать два параметра, во-первых, нам нужно указать строку, которую будем искать. Также нам нужна простейшая пагинация, чтобы указать сколько результатов поиска вернуть и сколько нужно результатов проигнорировать в начале поиска. q - строка для поискового запроса from - начальный индекс в списке результатов size - количество результатов для возвращения ЗаполнениеЗаполняющий endpoint получает только один параметр, который используется для определения количества результатов для генерирования. number - количество результатов для вставки в Elasticsearch Endpoint’ыТеперь, когда мы знаем структуру нашего микросервиса и какие endpoint’ы и параметры нам нужны, давайте начнем с писать код! Во-первых, сначала создадим главный файл main.go с endpoint’ами и базовым HTTP-сервером. 1234567891011121314151617181920package mainimport ( \"log\" \"net/http\")func main() { mux := http.NewServeMux() mux.HandleFunc(\"/populate\", func(w http.ResponseWriter, req *http.Request) { }) mux.HandleFunc(\"/search\", func(w http.ResponseWriter, req *http.Request) { }) log.Fatal(http.ListenAndServe(\":8000\", mux))} Поскольку это достаточно маленький микросервис, мы создадим endpoint’ы непосредственно в файле main.go. Но в продакшн или если у вас больше логики, лучше перенести эти endpoint’ы в отдельный файлы. Теперь, давайте напишем поисковой endpoint. Нам нужно будет получить get параметры, что относительно неуклюже и долго, когда вы используете стандартную библиотеку Golang, поэтому я не буду описывать это в статье, если вам интересно, то метод описан на GitHub. После получения параметров мы проверяем, правильны ли они, если нет, то отправляем ответ, что это недопустимый запрос. После этого мы передаем параметры term, from и size в нашу функцию поиска в Elasticsearch, которую мы создадим в следующем разделе. Функция будет опрашивать Elasticsearch и возвращать результаты, а также ошибку, если таковая случится. Оттуда мы будем формировать json ответ и отправлять его клиенту. Довольно просто. 1234567891011121314151617mux.HandleFunc(\"/search\", func(w http.ResponseWriter, req *http.Request) { term, from, size, ok := getQueryParams(req) if !ok { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(\"Attach proper parameters\")) return } res, err := Search(term, from, size) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(\"Error searching\")) return } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(res)}) Следующая задача - создать endpoint для заполнения Elasticsearch. Наличие endpoint’а поиска не имеет смысла, если у нас нет данных для поиска! Первое, что мы делаем, это получить get параметр number и переобразовать его в целое число. Если он неправильный, мы возвращаем отрицательный ответ клиенту. Следующий шаг - заполнить Elasticsearch, это делается с помощью вспомогательной функции, которую мы сделаем позже в этой статье. Наконец, мы возвращаем ошибку, если функция заполнения отдает ошибку. 123456789101112131415161718192021mux.HandleFunc(\"/populate\", func(w http.ResponseWriter, req *http.Request) { numberArr, ok := req.URL.Query()[\"number\"] if !ok { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(\"Attach proper parameters\")) return } numberStr := numberArr[0] number, err := strconv.Atoi(numberStr) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(\"Attach proper parameters\")) return } err = Populate(number) if err != nil || !ok { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return }}) Теперь, когда мы создали endpoint’ы, нам нужно связать все это вместе с функциями Elasticsearch. Elasticsearch HelpersПоследняя часть создания микросервиса это подключение к Elasticsearch. Давайте создадим helper’ы сейчас, мы сделаем это в новом файле elastic.go. Давайте посмотрим, как должен выглядеть файл, сначала нам нужна json-модель для Elasticsearch. Вам нужно создать структуру пользователя User со следующими полями: Username с json-декоратором username Email с json-декоратором email RealName с json-декоратором real_name Нам также необходимо создать функции Populate и Search. 12345678910111213141516171819202122package mainimport ( \"context\" \"github.com/olivere/elastic\" \"github.com/icrowley/fake\" \"encoding/json\")type User struct { Username string `json:\"username\"` Email string `json:\"email\"` RealName string `json:\"real_name\"`}func Populate(number int) error {}func Search(term string, from, size int) ([]*User, error) {} Теперь, когда мы написали макет, следующий шаг - создать методы. Мы используем github.com/olivere/elastic для работы с Elasticsearch. Теперь создадим логику для функции поиска. Первый шаг это соединиться к поиску Elastic и мы сделаем это создав новый клиент. Если соединение прошло успешно мы формируем запрос. Мы используем многопоточный запрос, если вам интересны другие параметры вы можете найти их в документации Elasticsearch. Наконец, мы вызываем метод Search и передаём корректные параметры, используем индекс пользователя, и передаём ранее созданный многопоточный запрос и добавляем пагинацию. В ответ мы получим много довольно интересной информации, но для нашего микросервиса мы не занимаемся журналированием или аналитикой, поэтому нас интересуют только результаты поиска. Мы проходимся циклом по результатам и используем json.Unmarshal, чтобы добавить пользователей в нашу структуру и затем добавляем структуру в массив, чтобы передать клиенту. 123456789101112131415161718192021222324252627func Search(term string, from, size int) ([]*User, error) { client, err := elastic.NewClient(elastic.SetURL(\"http://elasticsearch:9200\")) if err != err { return nil, err } q := elastic.NewMultiMatchQuery(term, \"username\", \"email\", \"real_name\").Fuzziness(\"AUTO:2,5\") res, err := client.Search(). Index(\"users\"). Query(q). From(from). Size(size). Do(context.Background()) if err != nil { return nil, err } users := make([]*User, 0) for _, hit := range res.Hits.Hits { var user User err := json.Unmarshal(*hit.Source, &user) if err != nil { return nil, err } users = append(users, &user) } return users, nil} Функция Populate начинается почти также, нам нужно подключится к клиенту. Но мы проверяем, существует ли индекс, и если нет, то создаем его. Затем мы используем библиотеку для генерации фальшивых пользователей, генерируем и передаем их в функцию, и вставляем в Elasticsearch. 12345678910111213141516171819202122232425262728293031func Populate(number int) error { client, err := elastic.NewClient(elastic.SetURL(\"http://elasticsearch:9200\")) if err != nil { return err } idxExists, err := client.IndexExists(\"users\").Do(context.Background()) if err != nil { return err } if !idxExists { client.CreateIndex(\"users\").Do(context.Background()) } for i := 0; i < number; i++ { user := User{ Username: fake.UserName(), Email: fake.EmailAddress(), RealName: fake.FullName(), } _, err = client.Index(). Index(\"users\"). Type(\"doc\"). BodyJson(user). Do(context.Background()) if err != nil { return err } } return nil} Настраиваем DockerДля этой системы я выбираю docker-compose, чтобы связать поисковый микросервис с Elasticsearch. В документации Elasticsearch есть отличная статья по этому поводу. Я последовал за этой статьей с несколькими небольшими изменениями. Единственная часть, на которой нам нужно сосредоточиться, - это Dockerfile, а также привязка его к Elasticsearch через docker-compose. Dockerfile довольно простой, мы загружаем docker образ Golang 1.10 alpine, добавляем dep для нашего менеджера зависимостей, добавляем путь к коду в GOPATH, получаем зависимости с dep, компилируем программу и запускаем ее. 12345678910111213141516171819FROM golang:1.10-alpineLABEL authors=\"Ryan McCue <ryan@msys.ca>\"RUN apk add --no-cache ca-certificates openssl gitRUN wget -O /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 && \\ chmod +x /usr/local/bin/depRUN mkdir /go/src/appADD . /go/src/app/WORKDIR /go/src/appRUN dep ensureRUN go build -o main .CMD [\"/go/src/app/main\"] Файл docker-compose.yml стандартный, он основан на этом с добавлением службы поиска и добавлением в esnet. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859version: '2.2'services: search: container_name: search build: context: . dockerfile: ./Dockerfile volumes: - ./search:/www ports: - \"8080:8000\" networks: - esnet elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4 container_name: elasticsearch environment: - cluster.name=docker-cluster - bootstrap.memory_lock=true - \"ES_JAVA_OPTS=-Xms512m -Xmx512m\" ulimits: memlock: soft: -1 hard: -1 volumes: - esdata1:/usr/share/elasticsearch/data networks: - wsdnet healthcheck: test: \"curl -f http://localhost:9200 || exit 1\" interval: 1s retries: 20 networks: - esnet elasticsearch2: image: docker.elastic.co/elasticsearch/elasticsearch:6.2.4 container_name: elasticsearch2 environment: - cluster.name=docker-cluster - bootstrap.memory_lock=true - \"ES_JAVA_OPTS=-Xms512m -Xmx512m\" - \"discovery.zen.ping.unicast.hosts=elasticsearch\" ulimits: memlock: soft: -1 hard: -1 volumes: - esdata2:/usr/share/elasticsearch/data networks: - esnetvolumes: esdata1: driver: local esdata2: driver: localnetworks: esnet: Чтобы проверить и убедиться, что файлы работают вместе, как и планировалось, выполните docker-compose build для построения поискового микросервиса, а затем запустите docker-compose up для запуска кода. Elasticsearch будет собран в docker-compose up, поэтому не беспокойтесь, если вы заметите это. Запуск!Теперь, когда микросервис написан и взаимодействует с Elasticsearch, пришло время проверить его. Давайте запустим наши endpoint’ы и посмотрим, что произойдет! Во-первых, мы должны заполнить Elasticsearch результатами, поэтому давайте запустим endpoint /populate. Вы можете запустить его с помощью ссылки ниже:1http://localhost:8080/populate?number=100 После заполнения следующий шаг - поиск результатов. Поскольку мы используем Faker, имена не известны заранее, поэтому вам, возможно, придется попробовать пару имен, прежде чем вы увидите результаты. Вы можете запустить поисковой endpoint с помощью ссылки ниже:1http://localhost:8080/search?q=ryan&from=0&size=20 ЗаключениеЭта статья показывает как можно легко сделать микросервис для таких сервисов, как поиск, и подключить его для работы с Elasticsearch. В реальной системе вы не будете генерировать случайные данные, вы, вероятно, будете использовать webhooks или системы очередей для заполнения поиска. Источник: ryanmccue","categories":[{"name":"Статьи","slug":"Статьи","permalink":"http://40pk.github.io/categories/Статьи/"}],"tags":[{"name":"Перевод","slug":"Перевод","permalink":"http://40pk.github.io/tags/Перевод/"},{"name":"API","slug":"API","permalink":"http://40pk.github.io/tags/API/"},{"name":"Golang","slug":"Golang","permalink":"http://40pk.github.io/tags/Golang/"},{"name":"Микросервис","slug":"Микросервис","permalink":"http://40pk.github.io/tags/Микросервис/"},{"name":"Elasticsearch","slug":"Elasticsearch","permalink":"http://40pk.github.io/tags/Elasticsearch/"}]}]}