Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Веселая аркада с Печенькой для новогоднего настроения. Объезжайте препятствия, а подарки, варежки, конфеты и прочие приятности не объезжайте: они помогут набрать очки и установить новый рекорд.

Сноуборд

Спорт, Аркады, На ловкость

Играть

Топ прошлой недели

  • Rahlkan Rahlkan 1 пост
  • Tannhauser9 Tannhauser9 4 поста
  • alex.carrier alex.carrier 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
20
CGAleksey
CGAleksey
15 дней назад
IT-юмор

GO - время давно настало⁠⁠

Мы с одногрупником в вузе изучали С++ и немного завидовали разработчикам на Java. Ну как немного, порой очень даже и много.

Нам казалось что в Java все работает максимально автоматизированно, так: ".сделай (аргументы)"
Если принимающему лабораторную не нравится, то делали так: ".сделай_лучше (аргументы)"
А если вообще по-царски нужно было сделать: ".сделай_вообще_супер_чтобы_было (аргументы)"

Сегодня дожили, заехал в Go... Так мне делать там почти ничего не надо кроме как знать какие пакеты подключать и вообще понимать что и как работает в этой жизни. Copilot вон, зависимости добавляет, куски кода пишет ДО того как я еще начинаю думать о них. Остается только смотреть верно среда догадывается о том, что мне нужно или нет.

Да, Go - совсем не C++ и далеко не Java.

[моё] Golang C++ Java Опыт Личный опыт Текст
35
pankovri
pankovri
27 дней назад

Думаешь, ты всё знаешь про defer в Go?⁠⁠

А знаешь ли ты, что за этим простым словом скрывается целый внутренний механизм с собственным стеком и хитрыми оптимизациями?

Думаешь, ты всё знаешь про defer в Go? IT, Golang

💡 В нашем новом посте я разбираю:

- В какой момент вычисляются параметры для defer

- Как defer устроен внутри Go runtime — с реальными структурами и флагами

- Какие крутые оптимизации появились в последних версиях Go, чтобы defer не тормозил программу

- В каких случаях стоит использовать этот механизм, а когда лучше этого не делать

Ссылка на пост https://teletype.in/@pankovri/t7rZdUQ5FqG

Показать полностью 1
[моё] IT Golang
1
2
pankovri
pankovri
1 месяц назад

Пишем desktop приложение на Golang + небольшой реверс инжениринг API POS-системы⁠⁠

Вводная часть

Зачем я вообще взялся за всё это? В одном небольшом розничном магазине стоит POS-система с не самыми гибкими настройками. Нужно было сделать так, чтобы продавец не видел остатки товаров в магазине — он продаёт только то, что отображается. Но! В некоторых разделах каталога остатки всё же должны быть видны. Для чего — это уже вопрос бизнес-логики.

Конечно можно было бы использовать API POS-системы, но они нагло запросили за это денег😁

Реверс инжениринг API POS-системы

Логинюсь в POS-систему под админом и открываю dev-tools браузере. Вижу, что используется reactjs, что для меня было хорошо. Перехожу в каталог. В каталоге все товары разбиты по категориям, открываю категорию и вижу, что данные приходят по Ajax. Соответственно, если данные приходят через ajax, то на бэкенд должен отправляться какой-то ключ аутентификации (jwt, access-token и т.д.). Это в общем база при HTTP запросах. Остаётся понять, как это работает.

Запросы уходят на https://my-pos-system.ru/service/?x_version=25.2155-162.10 с помощью HTTP POST метода. Долго не думая, кликнул правой кнопкой мыши на запросу Copy -> Copy as cURL

curl 'https://my-pos-system.ru/service/?x_version=25.2155-162.10' \

-H 'accept: application/json, text/javascript, */*; q=0.01' \

-H 'accept-language: ru-RU;q=0.8,en-US;q=0.5,en;q=0.3' \

-H 'cache-control: no-cache' \

-H 'content-type: application/json; charset=UTF-8' \

-H 'origin: https://my-pos-system.ru' \

-H 'pragma: no-cache' \

-H 'priority: u=1, i' \

-H 'referer: https://my-pos-system.ru/page/nomenclature-catalog' \

-H 'sec-ch-ua: "Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \

-H 'sec-ch-ua-mobile: ?0' \

-H 'sec-ch-ua-platform: "macOS"' \

-H 'sec-fetch-dest: empty' \

-H 'sec-fetch-mode: cors' \

-H 'sec-fetch-site: same-origin' \

-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \

-H 'x-calledmethod: Nomenclature.List' \

-H 'x-originalmethodname: Nf32Jkl4342nafi4=' \

-H 'x-requested-with: XMLHttpRequest' \

-b $'lang=ru; region=RU; DeviceId=qqqq-qqqq-qqqq-qqqq-qqqq; _ym_uid=123; _ym_d=1234; ... и далее много чего в куках' \

--data-raw '{"jsonrpc":"2.0","protocol":7,"method":"Nomenclature.List","params": ... и далее большой json в теле запроса'

Выполнил в консоли запрос и пришёл необходимый мне ответ от POS-системы. Это было небольшой успех, т.к. значит, можно отравлять и получать запросы.

Изучив curl запрос, предположил, что данные для аутентификации передаются через cookie. Удалил всё лишнее и выполнил запрос

curl 'https://my-pos-system.ru/service/?x_version=25.2155-162.10' \ -b $'lang=ru; region=RU; DeviceId=qqqq-qqqq-qqqq-qqqq-qqqq; _ym_uid=123; _ym_d=1234; ... и далее много чего в куках' \ --data-raw '{"jsonrpc":"2.0","protocol":7,"method":"Nomenclature.List","params": ... и далее большой json в теле запроса'

В ответ пришел 403 HTTP код. Значит удалил, что-то лишнее. Начал потихоньку пробовать возвращать параметры в curl и через пару минут понял, что не хватает заголовка -H 'content-type: application/json; charset=UTF-8'

Добавил в запрос и выполнил

curl 'https://my-pos-system.ru/service/?x_version=25.2155-162.10' \ -H 'content-type: application/json; charset=UTF-8' \ -b $'lang=ru; region=RU; DeviceId=qqqq-qqqq-qqqq-qqqq-qqqq; _ym_uid=123; _ym_d=1234; ... и далее много чего в куках' \ --data-raw '{"jsonrpc":"2.0","protocol":7,"method":"Nomenclature.List","params": ... и далее большой json в теле запроса'

Необходимый ответ пришёл. Это успех. Значит можно переходить к кодингу.

Ответ в JSON там очень большой, подробно разбирать его не будет, это не сильно интересно. Много полей с названиями полей f, a, t и т.д., но опытным путём нашёл какие поля необходимы. Мне нужно было найти только название номенклатуры, описание и остаток. Кто в своей юности использовал ArtMoney для получения бесконечных жизней и ресурсов в играх меня поймут. Взял первоначальный ответ, потом поправил в необходимые параметры в POS-системе и снова сделал запрос. Нашёл поля, которые изменились, они то мне и нужны.

Стек

К выбору стека исходил из своих навыков. Можно было конечно взять C++ и начал писать, но это не мой случай. Нужно быстро и чтобы я мог поддерживать это. Оценив свои навыки PHP, Golang, JS (TS), немного reactjs, начал гуглить, что вообще есть. Есть отличный фреймворк electron на котором написано ряд популярных приложений (slack, postman).

В общем взял electron начал создавать проект и компилировать его. Из плюсов, он очень мощный, можно копилить сразу под разные платформы. Развернул проект, начал компилить и у меня упорно не хотела происходить сборка. Потратив вечер на борьбу с electron, не хотел тратить много времени, решил погуглить ещё варианты. Нашёл фреймворк Wails на котором можно писать на Golang + JS (TS). Развернул и скомпилировал пустой проект за 5 минут. Было принято решение использовать его.

По итогу экспериментов на пустом проекте у меня получился такой стек:

  • Golang — backend-прослойка и основа приложения.

  • Wails — фреймворк для сборки desktop-приложений с UI на web-технологиях и backend на Go.

  • React — библиотека для построения интерфейсов.

  • TypeScript — типизированное надмножество JavaScript, упрощающее разработку и отладку.

  • MUI (Material UI) — готовый набор компонентов интерфейса в стиле Material Design.

Такой стек позволяет быстро разрабатывать современное desktop-приложение с мощной логикой на Go и удобным интерфейсом на React.

Инициализация wails

Первым шагом создадим базовый каркас desktop-приложения с использованием Wails

Установка Wails

Перед установкой убедитесь, что у вас установлен Go (версия 1.20+) и Node.js. Затем установим сам CLI:

go install github.com/wailsapp/wails/v2/cmd/wails@latest

Проверьте, что всё установилось корректно:

wails doctor

Если появилась надпись SUCCESS Your system is ready for Wails development! значит всё установилось и готово к работе

Создание проекта каркаса проекта

Создаём новый проект с шаблоном React + Vite + TypeScript:

wails init -n catalog-desktop -t react-ts

В результате структура проекта будет выглядеть примерно так:

Пишем desktop приложение на Golang + небольшой реверс инжениринг API POS-системы Golang, API, Компьютер, Telegram (ссылка), Длиннопост

Запуск в режиме разработки

Перейдём в директорию проекта и запустим в dev-режиме:

cd catalog-desktop

wails dev

Эта команда одновременно запускает frontend (с hot reload через Vite) и backend на Go. Любые изменения в интерфейсе или логике пересобираются автоматически.

При успешной сборке у вас откроется окно приложения

Пишем desktop приложение на Golang + небольшой реверс инжениринг API POS-системы Golang, API, Компьютер, Telegram (ссылка), Длиннопост

👨‍💻 Код по итогу итерации

Создание UI

Для начала установим зависимости которые нам необходимы для UI.

Переходим в папку frontend и выполняем команду

npm install --save typescript @types/react @types/react-dom @emotion/styled @mui/material axios

Требования у меня были следующие:

- Отобразить данные в виде таблицы

- При запуске приложения сходить в POS-систему получить необходимые данные

- Необходимо обновлять данные из POS-системы раз в 1 минуту

- Отобразить кнопку обновить, чтобы кассир мог вручную обновить данные из POS-системы

Вот так я это примерно видел

Пишем desktop приложение на Golang + небольшой реверс инжениринг API POS-системы Golang, API, Компьютер, Telegram (ссылка), Длиннопост

Постараюсь описать в статье как можно меньше кода, т.к. в конце будет репозиторий со всем кодом.

Отобразить данные в виде таблицы

Для начала набросал UI, как это должно выглядеть.

Особо красивый код я не стал делать, поэтому пошло как пошло.

По итогу получился вот такой "дизайн"

Пишем desktop приложение на Golang + небольшой реверс инжениринг API POS-системы Golang, API, Компьютер, Telegram (ссылка), Длиннопост

👨‍💻 Код по итогу итерации

При запуске приложения сходить в POS-систему получить необходимые данные

Забегая немного вперед, после написания кода для получения необходимых данных из POS-систему я столкнулся с CORS проблемой. Как я это решал, будет позже, пока пишем код.

Накидал метод handleRequest который будет отвечать за запрос к POS-системе. Он будет использоваться при старте приложения, при автоматическом обновлении и хэндлером для кнопки ручного обновления.

Так же решил добавить лоадер и вывод ошибок

👨‍💻 Код по итогу итерации

Необходимо обновлять данные из POS-системы раз в 5 минут

Тут всё просто, особо говорить нечего. Запускаем таймер и дёргаем handleRequest

👨‍💻 Код по итогу итерации

Отобразить кнопку обновить, чтобы кассир мог вручную обновить данные из POS-системы

Тут ещё проще, берём handleRequest и навешиваем на событие onClick единственной кнопки UI

👨‍💻 Код по итогу итерации

Проблема с CORS

Как я уже упоминал, столкнулся с проблемой CORS — политики безопасности браузеров, которая блокирует запросы между разными доменами. Из-за этого нельзя напрямую отправлять запросы в POS-систему. Чтобы обойти это, сервер должен возвращать в заголовках значение Access-Control-Allow-Origin, разрешающее такие запросы.

Чтобы обойти эту проблему, нужен был прокси. Самый простой вариант — поднять веб-сервер прямо в приложении и ходить через него в POS-систему. Но у Wails есть одна интересная фишка: можно писать логику на Go и вызывать её из JavaScript. Магия, подумал я — и решил попробовать.

Немного вайбкодинга(да я вначале хотел проверить теорию, сработает ли и только потом углубляться в технические составляющие) и у меня получился вот такой комит.

👨‍💻 Код по итогу итерации:
https://github.com/roman-pankov/catalog-desktop/commit/7a1d2902f4fdab3933c93bc3ae9699f0426e4fdd

Немного теории о Wails и IPC

Wails для этой магии использует IPC(Inter-Process Communication). IPC (Inter-Process Communication) — это набор механизмов, позволяющих двум или более процессам обмениваться данными между собой.

В случаем wails используется WebView messaging. WebView messaging — это механизм обмена сообщениями между веб-содержимым (WebView) и внешним приложением. Он позволяет вызывать действия на стороне приложения в ответ на события, происходящие в WebView, и наоборот. При этом запрос не отправляется через сеть.

Примерно так выглядит жизненный цикл запроса

[Frontend] window.backend.MyService.Hello("World")

↓ (WebView messaging)

[Nativе Bridge] Получаем JSON: {service: "MyService", method: "Hello", params: ["World"]}

↓

[Go] Выполняем метод MyService.Hello("World") → "Hello World"

↓

[Nativе Bridge] Возвращаем результат

↓

[Frontend] Promise resolved → "Hello World"

Сборка

Для сборки приложения достаточно выполнить команду wails build. В результате в папке build/bin будет создан исполняемый файл.

Главное преимущество Wails в том, что он не включает в себя целый браузер, как это делает Electron. Благодаря этому итоговый размер моего приложения составил всего 9.5 МБ.

Но есть нюанс — для каждой платформы (Windows, Linux, MacOS) придётся собирать приложение в её родной среде.

Итоги

После нескольких вечеров экспериментов с Electron и Wails мне удалось решить поставленную задачу. Код, конечно, пока далёк от идеала — многое можно переписать и оптимизировать. Кто-то может указать на небезопасность хранения авторизационной куки прямо в приложении, но в моём случае вопрос безопасности был не приоритетом: приложение должно работать в единственном экземпляре на рабочем месте кассира.

С развитием ИИ подход к таким задачам сильно упростился — просто набрасываешь код, запускаешь, проверяешь, как работает, и уже по ходу разбираешься, что и как. Быстро, гибко и эффективно — настоящий вайб кодинга в наше время.

Код на github https://github.com/roman-pankov/catalog-desktop

👉 Подписывайтесь на по ТГ буду стараться писать что-то полезное и интересное https://t.me/+fhVmaCi66s9kMDBi

Показать полностью 4
Golang API Компьютер Telegram (ссылка) Длиннопост
0
133
imctobitch
imctobitch
1 месяц назад
IT-юмор
Серия I'm CTO, bitch

Современный стек⁠⁠

Современный стек
[моё] I`m CTO bitch IT юмор Разработка PHP Golang Python Java Языки программирования Программирование Юмор Переписка Kotlin Csharp Мат
83
3
Vetal44
Vetal44
1 месяц назад
Язык программирования Rust

Как работает кеш процессора — и почему твой код ТОРМОЗИТ!⁠⁠

Программирование Golang Компьютер Оптимизация Видео Видео ВК
2
9
user10516742
user10516742
2 месяца назад
Лига программистов

Почему JS (и TS) это плохой язык⁠⁠

Я знаю, что на эту тему уже было сказано много, но настал мой черед. На JS я пишу больше 10 лет, так что терпел я достаточно :)

Когда мы говорим “джаваскрипт”, мы подразумеваем много разных вещей:

  • Стандарт EcmaScript

  • Среда исполнения (NodeJS, браузер)

  • Экосистема (библиотеки, фреймворки, тулинг)

Иногда есть смысл поговорить об этих вещах по отдельности, но сегодня мы обсудим их все сразу, и назовем это просто “джаваскрипт”. А именно, я объясню, почему джаваскрипт это плохой язык.

Что значит плохой?

А что значит “плохой” (или хороший)? Кто-то из великих сказал: “есть 2 типа языков, те которые не ругают, и те на которых пишут”. Джаваскрипт буквально олицетворяет вторую категорию: его ругают почем свет стоит, и при этом он самый популярный язык программирования в мире.

JS это хороший язык в том смысле, что он, определенно, решает свою задачу (иначе он не был бы столь популярен), и это очень плохой язык в смысле того, насколько много усилий нужно приложить, чтобы решить тривиальную задачу.

Если последнее утверждение кажется вам неочевидным (как же так, hello world на JS можно написать в 1 строку, а на условном Go в 5-10), то нужно уточнение — программисты не слишком часто пишут хеловорды на работе. Чаще всего человеку, волею судеб столкнувшемуся с JS нужно работать с графическим интерфейсом, либо писать серверный код, и размеры таких приложений в большинстве своем превышают тысячу строк кода.

JS не масштабируется

Не даром слоган TS — “JavaScript that scales”. Во всяком случае, был. Этот язык был спроектирован много лет назад для решения задач, которые совершенно не похожи на сегодняшние. Написать скрипт, максимум, в несколько сотен строк кода это совершенно не то же самое, что поддерживать огромный проект с десятками сложнопереплетенных сущностей, где цена отказа это большие деньги.

Да, разработчики EcmaScript и движков вроде V8 большие молодцы, что развивают язык. Так, например, в нем со временем появились импорты и async-await, но, во-первых, там есть нюансы (об этом чуть позже), а, во-вторых, этого недостаточно. Помимо этого нужна как минимум статическая типизация, линтинг и форматтер. Если мы говорим про фронтенд среднего и выше размера, то добавьте сюда: минификацию, обфускацию, сжатие картинок, транспиляцию под старые браузеры и, черт знает, что еще. Вам может особенно “повезти”, если вы разрабатываете под какую-то нестандартную платформу вроде Chrome или VSCode расширения, где на вас упадут дополнительные ограничения с которыми вы останетесь один на один. И часто проблема решается написанием каких-то кастомных скриптов для сборки вашего кода каким-то нетривиальным способом.

Короче, из коробки JS годится лишь для написания очень маленьких вещей, а как только ситуация меняется, начинаются маневры, и поверх основной технологии (собственно, языка), начинают наслаиваться дополнительные, и все это (из-за основной причины, отсутствия нужных инструментов в самом языке), ходит ходуном и шатается от ветра как карточный домик.

Итого, JS “из коробки” не масштабируется — факт. Для масштабирования требуется сильное усложнение системы путем добавления в нее компонентов неочевидного качества. И дело даже не в комьюнити - разработчики сторонних инструментов большие молодцы, что решают насущные проблемы, но они просто не могут решить их по настоящему качественно, потому они сами вынуждены писать на джаваскрипте. Это рекурсия и порочный круг.

Фронтенд это боль

Как вы могли понять из предыдущего абзаца, проблема “JS не предоставляет из коробких нужных инструментов” удесетеряется в случае, если вы пишете не для сервера, а под браузер. Это забавно, учитывая, что JS был создан для фронтенда, а бэкенд на нем, в итоге, писать проще.

Это не значит, что надо тащить JS на бэкенд, он все еще остается плохим языком, просто на фронтенде страданий еще больше. К тому же, злая ирония такова, что на бэкенде, где JS еще можно как-то стерпеть, есть из чего выбрать (например, Go), а вот на фронтенде выбора нет. Более того, выбор может пасть на JS (и вполне адекватно, к сожалению) даже когда вы пишете мобильное и/или десктопное приложение, например, на React Native или Electron. Как сложилась такая ситуация, отдельная история, но это факт, и с ним надо мириться.

Ситуация с фронтендом настолько ужасна, что самый популярный и стабильный фреймворк React заставляет вас писать на языке jsx (tsx), который является абстракцией над JS и HTML. Альтернативы еще хуже, например, Svelte также добавляет свой html-js-подобный язык с различными магическими директивами.

В итоге этот “динамический” язык не работает без кучки компиляторов, каждый из которых имеет свои конфиги, свою экосистему плагинов (каждый из коротых в любой момент может может сломать обратную совместимость, не обновиться вовремя, стать depracated и прочее).

Веб нельзя ломать

Логика разработчиков JS проста — миллионы сайтов и приложений работают на джаваскрипте, следовательно, из джаваскрипта ничего нельзя удалить. В итоге в него все добавляют и добавляют, как следствие, на нем можно писать в десяти разных стилях и одна проблема решается дюжиной разных способов. Как думаете, как это влияет на качество и удобство разработки? Правильно, влияет очень плохо. Два проекта даже на React могут выглядеть совершенно по разному, не говоря уже о проектах с разными фреймворками. Они даже синтаксически (из-за бесконечного юзания различных настроек и сахаров) легко могут отличаться.

Но это по беды. Так как ни одно минимально работающее приложение на JS невозможно без огромной пачки зависимостей (будь то рантайм или для тупо сборки), то будьте готовы к тому, что пакеты не дружат друг с другом. В одном пакете CommonJS импорты, в другом ES6 импорты, в третьем еще какая-нибудь херня. Или ситуация, что пакет который вам нужен внезапно не поддерживает нужный вам формат импортов.

Я остановлюсь тут, но, мне кажется, подобных причин для поломки, которые следуют из того факта, что “веб нельзя ломать” можно выдумать еще много.

TypeScript не помог

Опять же, не поймите неправильно. Ребята из Microsoft большие молодцы, что решают насущную проблему, и без них было бы намного хуже. Однако, их решение, во-первых, не решает проблему полностью а, во-вторых, добавляет своих проблем.

Начнем с того, что у вас в системе +1 компонент - компилятор тайпскрипта. У него (ну разумеется) есть свой конфиг. Версия вашего компилятора должна матчится с вашими зависимостями.

Далее, TypeScript не дает никаких гарантий. Вообще. Как же так? Компонент в систему добавили, +1 язык выучили, а undefined все еще is not a function? Причина в том, что TS был разработан для gradual adoption, то есть плавной интеграции с JS. Разработчики предположили (и правильно предположили), что просто взять и переписать весь джаваскрипт в мире на TS не получится, и любой TS-код будет взаимодействовать с небезопасным JSом. Как следствие, очень и очень часто в своем TypeScript проекте вы будете видеть тип any который как бы говорит “хз что это, делай с этим что хочешь но на свой страх и риск”. Классная типизация, да?

Выводы

  • JS это плохой язык и тулинг эту проблему не решает, видимо, потому что это просто невозможно в принципе

  • Иногда брать JS/TS можно и нужно, ситуации бывают разные, но это за пределами статьи

  • Если вы не писали на Go, советую попробовать, вы удивитесь, насколько жизнь может быть приятнее (как бонус еще и конская производительность)

Дополнительно

Я посвятил три года изучению языков программирования и написал свой. Он совсем не похож на JS потому что он потоко-ориентированный (dataflow/flow-based) и в нем все работает параллельно by default. В его архитектуру я заложил все, чтобы работать с ним было легко и приятно. К сожалению, сейчас у меня нет времени заниматься им, но мне будет приятно, если вы на него посмотрите.

https://github.com/nevalang/neva

Мои Telegram Каналы

Еще у меня есть 2 tg канала где я пишу про запуск своего проекта и программирование с помощью LLM.

  • https://t.me/ai_coder_channel

  • https://t.me/build_saas_in_public

Показать полностью
[моё] Javascript Typescript Golang Языки программирования Мнение Текст Длиннопост
29
0
Вопрос из ленты «Эксперты»
user8711267
3 месяца назад

Хочу изучить алгоритмы на языке Go - нужен совет⁠⁠


Привет всем!

Я недавно начал изучать язык Go (Golang). Сначала изучал самостоятельно, потом прошел бесплатные курсы, потом подумал, что может в платных курсах есть что-то более конкретное или углубленное, прошел полугодовой курс (платный). Не хочу указывать в статье что именно за курсы, что бы не было рекламой. По факту хочу сказать, что разница не особо большая - но было кое-что полезное - сроки, и хоть какой-то фидбек от преподавателя. Сейчас хочу попасть на стажировку (Авито/озон/т-банк/да в принципе хоть что-то). Не знаю - верный ли путь я намечаю или нет. Если в комментариях скажите что-то по этому поводу - будет хорошо.

Так вот, что бы попасть на стажировку - необходимо пройти алгособес. Вот тут у меня пробел. Хочу изучить как решать алгоритмические задачи на go. На python много материалов на эту тему в интернете, на других ЯП тоже хватает, но именно на Go я встречал только платные варианты.

Посоветуйте пожалуйста какие-нибудь бесплатные материалы (мне зашёл формат текстовый, видео - не очень, но если другого нет, то мне и это пойдет). Может какие-то книги, курсы. Хотелось бы именно подборкой цельной. Я нахожу разные статьи на Хабре, какие-то бесплатные обрезки курсов. В общем всё кусками. А хочется что-нибудь более структурированное и полное.

Раньше я немного сталкивался с алгоритмами на других языках, но хочется пройти весь путь именно на Go: от базовых сортировок и деревьев до более сложных задач типа графов, динамичес

Просьба к вам уважаемые гоферы с Пикабу:

Поделитесь пожалуйста информацией.

Буду благодарен за любые советы, ссылки и просто поддержку. Если есть желающие учиться вместе — тоже пишите в комменты или в ЛС!

Спасибо!

P.S. немного о себе - я с Иркутска (это для тех, кто может захочет объединить силы для совместного обучения, пишу для понимания часового пояса). Мне 32 года, есть основная работа, но чувствую, что необходимо менять, причин много, не буду расписывать. Почему именно IT? Потому как есть знакомые которые успешно перешли в эту сферу (предугадывая комменты - у них нет того, что мне нужно), немаловажно - зарплаты, плюс просто всегда нравилось взаимодействие с компьютером, в детстве мечтал стать программистом, с того момента как сисадмин учил меня играть в StarCraft😅

Показать полностью
[моё] Программирование Golang Помощь Компьютер Информация Программа Linux Программист Вопрос Спроси Пикабу
18
5
Dedero
4 месяца назад

Разбираем паттерны конкурентности⁠⁠

Разбираем паттерны конкурентности Программирование, Golang, Многопоточность, Backend, IT, Длиннопост

База

Параллельность - выполнение задач в один момент времени на разных логических ядрах.

Конкурентность - выполнение задач последовательно, но со сменой контекста на другую задачу в ожидание завершения иной задачи. У пользователя может возникнуть иллюзия многозадачности даже в однопроцессорной системе, поскольку смена контекста происходит быстро (микросекунды).

Процессы:

  • Раздельная память

  • Раздельные ресурсы

  • Раздельные регистры

Потоки:

  • Общая память

  • Общие ресурсы

  • Раздельные стэк и регистры

Горутины:

  • Общая память

  • Общие ресурсы

  • Общий системный стэк

  • Общие регистры

Go runtime представляет модель P:M:G.

P - представляет логическое ядро процессора.

M - поток ОС по числу процессоров P.

G - структура, которая выполняет переданную функцию, создаётся по необходимости, минимум одна на старте программы (main). Стэк всего 2кб, может расширятся до 1гб для 64x и до 250кб для 32х систем.

Управление горутинами осуществляется планировщиком Go, а не ОС. Планировщик Go работает в пользовательском пространстве. Мы не можем напрямую управлять на каком процессоре будет исполняться горутина, за это отвечает планировщик.

Канал - очередь сообщений, которая умеет работать в многопоточной среде, работает по принципу FIFO.

Есть два типа каналов: буферизованный и небуферизованный.

Первый может хранить несколько сообщений, второй только одно.

Синхронизация

sync.WaitGroup - счётчик, который позволяет подождать завершения горутин.

sync.Mutex - блокирует доступ к ресурсу.

sync.RwMutex - разделяемая блокировка на чтение и запись. Читать могут несколько горутин, но мутировать данные только одна.

sync.Atomic - атомарная операция чтения и записи. Работает только с простыми значениями.

sync.Map - lock-free структура. Работает так же, как и обычная map, но потокобезопасная, можно использовать в многопоточной среде. Хорошо подходит для случаев, где надо много читать и мало писать. Если надо много писать, то лучше использовать обычную map и sync.RwMutex.

Небуферизованный канал

Разбираем паттерны конкурентности Программирование, Golang, Многопоточность, Backend, IT, Длиннопост

Буферизованный канал

Разбираем паттерны конкурентности Программирование, Golang, Многопоточность, Backend, IT, Длиннопост

Ограничения канала

Разбираем паттерны конкурентности Программирование, Golang, Многопоточность, Backend, IT, Длиннопост

Важные правила

  • Закрывает канал тот, кто в него пишет.

  • Если пишет несколько продюсеров, то закрывает тот, кто создал продюсеров.

  • Не закрытый канал держит ресурсы. Закрывать надо явно.

Паттерны

Generator

Микропаттерн, который наполняет канал. Закрываем канал, чтобы не было проблем.

func generator() <- chan int {

ch := make(chant int)

go func(){

for i := 0; i <= 12; i++ {

ch <- i + 1

}

close(ch)

}()

return ch

}

Wrapper

Оборачиваем функцию, добавляя функциональность. Если вам что-то говорит слово декоратор, то это тот самый паттерн.

func wrapper(wg *sync.WaitGroup, fn func()) {

wg.Add(1)

go func() {

defer wg.Done()

fmt.Println("Work before func")

fn()

time.Sleep(1 * time.Second)

fmt.Println("Work after func")

}()

}

func main() {

var wg sync.WaitGroup

wrapper(&wg, func() {

time.Sleep(1 * time.Second)

fmt.Println("heavy work")

})

wg.Wait()

}

Fan-in

Собирает результаты из нескольких каналов в один.

func fanIn(input1, input2 <-chan string) <-chan string {

ch := make(chan string)

go func(){

for {

select {

case s := <-input1: ch <- s

case s := <-input2: ch <- s

}

}

}()

return ch

}

Fan-out

Одна или несколько горутин пишут в канал, с другой стороны рабочие горутины читают канал, делают работу и умирают.

func worker(ch <-chan int, wg *sync.WaitGroup) {

wg.Done()

for v := range ch {

fmt.Println(v)

time.Sleep(1 * time.Second)

}

}

func sender() {

ch := make(chan int)

var wg sync.WaitGroup

for i := 0; i < 2; i++ {

wg.Add(1)

go worker(ch, &wg)

}

for i := 0; i < 10; i++ {

ch <- i

}

close(ch)

wg.Wait()

fmt.Println("done")

}

Pipeline

Данные обрабатываются цепочкой. Producer -> Producer/Consumer -> Consumer. Стадий обработки может быть сколько угодно.

func producer() <-chan int {

c := make(chan int)

go func() {

for i := 0; i <= 10; i++ {

c <- i + 1

}

close(c)

}()

return c

}

func producerConsumer(c <-chan int) <-chan int {

out := make(chan int)

go func() {

for v := range c {

out <- v * 2

}

close(out)

}()

return out

}

func consumer(ch <-chan int) {

for v := range ch {

fmt.Println(v)

}

}

Rate limiting

Хотя для rate limiter есть множество разных алгоритмов, рассмотрим один, основанный на тиках.

func ticker() {

ch := make(chan int, 5)

go func() {

for i := 0; i < 5; i++ {

ch <- i

}

close(ch)

}()

limiter := time.Tick(time.Second)

for v := range ch {

<-limiter // будем ждать секунду

fmt.Println(v)

}

}

Cancellation

Способ прерывания горутин. Необходим, чтобы избегать висящих горутин, останавливать слишком долгие операции.

1. WithCancel

func worker(ctx context.Context) {

for {

select {

case <-ctx.Done():

fmt.Println("Done")

return

default:

fmt.Println("Working...")

time.Sleep(500 * time.Millisecond)

}

}

}

func main() {

ctx, cancel := context.WithCancel(context.Background())

go worker(ctx)

time.Sleep(1 * time.Second) // работаем

cancel() // отменяем

time.Sleep(1 * time.Second) // время на завершение

}

2. WithTimeout

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // спустя 2 секунды воркер перестанет работать

3. WithDeadline. Можно указать точное время остановки.

ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second)) // прибавляем к текущему времени две секунды

Worker Pool

Каждый воркер берёт задачу, делает работу и отправляет результат в канал, другая горутина, в нашем случае main, читает результат из канала.

func worker(jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {

defer wg.Done()

for j := range jobs {

time.Sleep(1 * time.Second)

fmt.Println("job", j)

results <- j * j

}

}

func main() {

jobs := make(chan int)

results := make(chan int)

var wg sync.WaitGroup

for i := 0; i < 3; i++ {

wg.Add(1)

go worker(jobs, results, &wg)

}

go func() {

for i := 0; i < 10; i++ {

jobs <- i

}

close(jobs)

}()

go func() {

wg.Wait()

close(results)

}()

for result := range results {

fmt.Println(result)

}

}

Actor model

Паттерн, при котором акторы общаются только через каналы, и меняют данные только через каналы.

type message struct {

amount int

response chan int

}

func counter(messages chan message) {

for m := range messages {

m.response <- m.amount + 1

close(m.response)

}

}

func main() {

messages := make(chan message)

var wg sync.WaitGroup

go counter(messages)

wg.Add(3)

for i := 0; i < 3; i++ {

go func(i int) {

defer wg.Done()

response := make(chan int)

messages <- message{amount: i, response: response}

fmt.Println(<-response)

}(i)

}

wg.Wait()

close(messages)

}

Это не все паттерны, их целая куча, но уже с этими можно делать интересные вещи, такие как балансировщики нагрузки, pub/sub системы, очереди задач, rate limiter и много всего другого.

Показать полностью 3
[моё] Программирование Golang Многопоточность Backend IT Длиннопост
3
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии