Golang Portal
8.06K subscribers
416 photos
26 videos
7 files
447 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Golang-разработчика

Связь: @devmangx
Download Telegram
Трюк для сокрытия методов и предотвращения утверждений интерфейсов в Go.

Например, есть тип A с методом Hello(), который удовлетворяет интерфейсу Greeter.
Если передать экземпляр A в Greet(), интерфейсное утверждение успешно пройдет, и будет вызван Hello().

Но если нужно использовать A, не открывая его метод Hello(), можно скрыть его через встраивание.
При вызове Greet(ANoHello{A: A{}}) интерфейсное утверждение провалится и выведет: "g does not implement Greeter".

Хотя ANoHello встраивает A, содержащий метод Hello(), неэкспортируемое поле noHello имеет приоритет и скрывает его.

Полезно в редких случаях (например, os.File), но стоит знать этот трюк для лучшего понимания встраивания.

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
💡 Шпаргалка по REST API для начинающих

Шесть фундаментальных принципов, которые служат строительными блоками архитектуры REST API:

Клиент-серверная архитектура
Взаимодействие без сохранения состояния
Возможность кэширования
Многоуровневая система
Поддержка кода по требованию
Унифицированный интерфейс

🔜 Читайте подробнее на Medium

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83
This media is not supported in your browser
VIEW IN TELEGRAM
Компилятор shell-скриптов, который превращает их в безопасные, переносимые и статические бинарные файлы.

В отличие от других инструментов, Bunster не просто упаковывает ваш скрипт в бинарник — он компилирует его в автономные программы, не зависящие от оболочки.

👉 https://github.com/yassinebenaid/bunster

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍52🌚1
Буферизированные каналы как семафоры для ограничения выполнения горутин

Когда нам нужно управлять тем, сколько горутин могут одновременно получить доступ к ресурсу, использование семафора — надежный подход.

Мы можем создать семафор с помощью буферизированного канала, где размер канала определяет, сколько горутин может выполняться одновременно. Вот как это работает:

🔹Горутин отправляет значение в канал, занимая одну ячейку.
🔹После завершения своей задачи он извлекает значение, освобождая тем самым эту ячейку для другой горутины.

В этом примере:

🔹wg.Add(10) — мы подготавливаемся к завершению 10 горутин.
🔹make(chan struct{}, 3) — это создает семафор, позволяющий одновременно работать только 3 горутинам.

Если нужен более аккуратный способ управления этим процессом, можно рассмотреть создание типа Semaphore, который будет обрабатывать все действия, связанные с семафором.

Использование такого пользовательского типа Semaphore упрощает управление доступом к ресурсам в наших функциях.

Также существует реализация семафора в пакете golang.org/x/sync/semaphore, которая представляет собой взвешенный семафор.

Взвешенный семафор позволяет горутине занимать более одной ячейки, что полезно в сценариях, когда задачи требуют разного объема ресурсов.

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

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111
⚙️ Веб-приложение для управляемой передачи файлов, созданное на Go, с использованием rclone для надежной передачи данных

https://github.com/StarFleetCPTN/GoMFT

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81
Настройка GOMAXPROCS для контейнерных сред (Kubernetes, Docker и др.)

⚠️ (Внимание: длинный и скучный материал)

Что такое GOMAXPROCS?

По умолчанию Go может запускать до 10 000 потоков одновременно, но фактическое количество потоков, выполняющихся параллельно, определяется важным параметром — GOMAXPROCS.

GOMAXPROCS устанавливает ограничение на количество потоков ОС, которые могут одновременно исполнять пользовательский Go-код (не просто конкуррентно, а именно параллельно).

Значение по умолчанию соответствует количеству логических ядер CPU, которое видит ОС (runtime.NumCPU()).

Например, на моем MacOS это 8 ядер, а значит, Go будет одновременно выполнять до 8 потоков.

Запуск Go в контейнерах (Docker и Kubernetes)

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

Пример:
🔹limit: 250m = 1/4 ядра
🔹limit: 1 = 1 полное ядро

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

(Хост-машина или нода может содержать несколько подов.)

Из-за этого Go-приложение может пытаться использовать больше процессорных ресурсов, чем ему выделено.

"Но почему? Ведь чем больше CPU, тем лучше!"

Вот несколько причин, почему это может быть проблемой:

Контекстные переключения – если потоков больше, чем ядер, ОС вынуждена чаще переключаться между ними.
Неэффективное планирование – планировщик Go создаёт больше готовых к выполнению горутин, чем CPU может реально обработать, что приводит к избыточной конкуренции за процессорное время.
Неэффективное выполнение CPU-bound задач – Go-программы часто CPU-bound, а значит, лучше работают, когда каждое ядро загружено ровно одним потоком без необходимости ожидания.

Если GOMAXPROCS больше, чем реально выделенные CPU-ресурсы, Go-рантайм планирует больше потоков, чем есть доступных ядер, что приводит к неэффективному выполнению.

Решение

Если хочется автоматизировать настройку, можно использовать uber-go/automaxprocs. Эта библиотека корректирует GOMAXPROCS в соответствии с ограничением CPU контейнера.

(Если интересно, как работает uber-go/automaxprocs под капотом — просто скажите.)

Если вы понимаете спецификацию деплоя/пода, можно вручную задать переменную окружения GOMAXPROCS в соответствии с лимитом.

Но с точки зрения DevOps лучше вовсе избегать CPU-лимитов, а вместо них устанавливать только CPU requests (об этом подробнее ниже). Это касается не только Go-сервисов.

Задумайтесь об этом, если в вашем контейнере не задан лимит CPU.

Полезные ссылки:
Почему не стоит использовать CPU-лимиты в Kubernetes
Kubernetes CPU Limits и Go

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍112
⚙️ Go-проект, который предоставляет программное решение для управления, хранения и распространения конфиденциальных данных, включая секреты, сертификаты и ключи

https://github.com/openbao/openbao

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2
Оптимизируйте множественные вызовы с помощью singleflight

Допустим, у вас есть функция, которая получает данные по сети или выполняет ввод-вывод, и её выполнение занимает около 3 секунд:

Эта функция выдаёт новое значение каждые 10 секунд.

🔹Если вызвать эту функцию 3 раза подряд, общее время ожидания составит примерно 9 секунд.
🔹Если использовать 3 горутины, общее время ожидания может сократиться до 3 секунд, но функция всё равно будет вызвана 3 раза для получения одного и того же результата (~99%).

Здесь на помощь приходит пакет singleflight, который доступен по ссылке:
👉 golang.org/x/sync/singleflight.

Этот пакет позволяет выполнить функцию только один раз, независимо от того, сколько раз она была вызвана за эти 3 секунды, и возвращает один общий результат.

Это отлично подходит для оптимизации функций, работающих долго или потребляющих много ресурсов.

Как это работает?
1️⃣ Создаём объект singleflight.Group
2️⃣ Передаём в метод group.Do() функцию, которая выполняет дорогостоящие вычисления.

Метод group.Do() возвращает:
(result any, err error, shared bool)

Параметр shared показывает, был ли результат разделён между несколькими вызовами.

Зачем нужен аргумент key?
Ключ (key) — это идентификатор запроса.
Если поступает несколько запросов с одним и тем же ключом, singleflight понимает, что они запрашивают одно и то же.

Пример работы: Go Playground

С этим подходом, если функция вызывается несколько раз одновременно, фактически выполняется только один её вызов. А результат этого единственного вызова разделяется между всеми ожидающими

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102
⚙️ Лёгковесный микросервис для обработки криптоплатежей, написанный на Golang, предназначенный для создания и обработки счетов в криптовалюте через gRPC

https://github.com/goipay/goipay

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62
Разбор DNS: от основ до создания DNS-сервера на Go

Статья объясняет основы DNS, процесс разрешения доменных имен и создание собственного DNS-сервера на Go.

Автор рассматривает работу DNS-запросов и делится проектом DNS-сервера с веб-интерфейсом на GitHub.

Полезно для изучающих сети и Go

👉 Читать

👉 @juniorGolang | #cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🤔1
⚙️ CLI-инструмент на Go для пакетного переименования файлов с использованием ИИ, позволяющий интеллектуально переименовывать несколько файлов одновременно путем анализа их содержимого и генерации осмысленных имен с помощью ИИ-моделей

https://github.com/Vein05/nomnom

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🔥1😁1
Фильтрация без лишних аллокаций

При фильтрации слайсов в Go стандартный подход — создание нового слайса для отфильтрованных элементов.

Однако такой метод приводит к дополнительным аллокациям памяти.

Более эффективный способ — фильтровать «на месте», используя исходный массив слайса.

Как это работает:
filtered := numbers[:0] создаёт новый слайс filtered, который ссылается на тот же массив, что и numbers, но имеет нулевую длину, сохраняя емкость numbers.
• Добавляя num в filtered, мы избегаем лишних аллокаций, так как просто изменяем содержимое numbers (или его базового массива).

Таким образом, мы не выделяем новую память, а заполняем уже существующий массив.

Этот метод особенно полезен, когда:
numbers больше не нужен после фильтрации.
• Критична производительность, особенно при работе с большими объемами данных.

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥73👎1
⚙️ Простой в использовании reverse proxy с интеграцией в Docker, написанный на Go

https://github.com/yusing/godoxy

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53