В Go строки
s[10:20] данные Чтобы экономить память, используйте
strings.Clone(substr)или string([]byte(substr)) для создания независимой Копируйте строки только если подстрока действительно живёт значительно дольше родителя — для кратковременной обработки, например, внутри обработчика запроса, срез без копирования эффективнее, так как выделение и копирование дороже, чем удержание лишней памяти.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Код 200 говорит клиенту: «Всё прошло штатно, держи результат». Если вместо результата внутри тела прячется ошибка, то клиент вынужден парсить ответ, чтобы понять, что запрос на самом деле провалился. Это ломает саму идею HTTP-контракта.
Когда это всё-таки допустимо? При ошибках бизнес-логики. Например, валидация формы вернула список замечаний: сам запрос обработан корректно, просто данные не прошли проверку на уровне домена. Но даже тут стоит трижды подумать.
Для всего остального в HTTP уже есть подходящие коды — и они существуют не просто так:
🔹
400 Bad Request — клиент прислал невалидные данные 🔹
404 Not Found — ресурс не существует 🔹
500 Internal Server Error — сервер сломался и не смог обработать запрос 🔹
503 Service Unavailable — сервер на паузе: перегрузка, деплой, обслуживаниеPlease open Telegram to view this post
VIEW IN TELEGRAM
❤6🥱1
Buffer.Peek(n), если в буфере меньше n байтBuffer.Peek возвращает срез доступных байт даже если их меньше n. Ошибки при этом нет. Поведение аналогично bufio.Reader.Peek, но там при нехватке байт возвращается io.ErrUnexpectedEOF — это распространённое заблуждение при переносе привычек из bufio.Please open Telegram to view this post
VIEW IN TELEGRAM
httputil.NewSingleHostReverseProxy и зачем он нуженNewSingleHostReverseProxy создаёт обратный прокси, который перенаправляет входящие HTTP-запросы на один заданный сервер. Вы передаёте функции целевой URL, а она возвращает http.Handler, готовый к использованию.Типичный сценарий это API-шлюз или балансировщик нагрузки перед сервисом. Вместо того чтобы писать логику проксирования вручную, можно получить готовый обработчик в несколько строк:
target, _ := url.Parse("http://backend-service:8080")
proxy := httputil.NewSingleHostReverseProxy(target)
http.ListenAndServe(":80", proxy)Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Алиас в Go это другое имя для существующего типа. Когда пишут
type Meters = float64, компилятор не создаёт новый тип: Meters и float64 взаимозаменяемы без явного приведения.Компилятор видит оба алиаса как
float64 и не различает их. Поэтому сложение, сравнение и передача в функцию работают без приведения типов. Если функция принимает Seconds, в неё без ошибки пройдёт переменная типа Meters.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ключевой критерий это количество методов в поведении. Если нужно абстрагироваться над одним действием, берите функцию-тип. Если поведение требует нескольких связанных методов — интерфейс.
Интерфейс оправдан, когда поведение требует нескольких связанных методов или когда реализация несёт внутреннее состояние — соединение, кэш, буфер. Тогда контракт нужно зафиксировать явно, и интерфейс делает это лучше.
Показательный пример из стандартной библиотеки —
net/http. Там оба подхода живут рядом: •
http.Handler — интерфейс с одним методом ServeHTTP•
http.HandlerFunc — функциональный тип, который реализует этот же интерфейс. Это позволяет передавать как структуры со состоянием, так и простые функции, не заставляя автора каждый раз писать обёртку.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1🌚1
sync.Pool не даёт гарантий на время жизни объектов. Поэтому Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Простого удаления файла и нового коммита недостаточно, потому что секрет
Нужно переписать историю через
git filter-branch или git filter-repo, удалив файл из всех коммитов. После этого обязательно отозвать скомпрометированные ключи, потому что они могли быть уже скачаны.Please open Telegram to view this post
VIEW IN TELEGRAM
Оба варианта
Сброс при
Get надёжнее, потому что гарантирует чистое состояние независимо от того, кто и как вернул объект в пул. Сброс при
Put экономит время на стороне потребителя, но требует дисциплины от всех, кто кладёт объекты обратно.Please open Telegram to view this post
VIEW IN TELEGRAM
t.Helper() и когда его вызыватьt.Helper() помечает функцию как вспомогательную. При падении теста стек ошибки укажет не на строку внутри хелпера, а на строку вызова в тесте.Когда вы выносите повторяющиеся проверки в отдельную функцию, Go по умолчанию при падении теста покажет в стеке строку внутри этой функции. Допустим, у вас есть хелпер
assertEqual, который вызывается в двадцати тестах. Тест упал, вы смотрите в лог и видите helper.go:14. Это строка с t.Errorf внутри хелпера. Чтобы понять, какой именно тест сломался, придётся идти по стеку вызовов вручную. Вызов в начале функции говорит Go, что эта функция вспомогательная, и при ошибке нужно показывать не её, а место вызова. Вместо
helper.go:14 вы увидите user_test.go:42, то есть конкретную строку теста, где всё пошло не так:// Без t.Helper() ошибка укажет на строку 3 этой функции
// С t.Helper() ошибка укажет на строку вызова assertEqual в тесте
func assertEqual(t *testing.T, got, want int) {
t.Helper()
if got != want {
t.Errorf("got %d, want %d", got, want)
}
}
Вызывать
t.Helper() нужно в каждой функции, которая сама не является тестом, но содержит вызовы t.Errorf, t.Fatalf или других методов, фиксирующих ошибку. Если хелпер вызывает другой хелпер, пометить нужно оба. Пропуск
t.Helper() не сломает тесты, они будут работать корректно. Но при отладке падений в большом проекте с десятками хелперов отсутствие этой пометки превращает чтение логов в квест. Привычка ставить t.Helper() первой строкой в любой вспомогательной функции экономит время и нервы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤4
Запускаете тесты с флагом
-cover для общей цифры. Для детального отчёта генерируете профиль и открываете его в браузере:go test -coverprofile=coverage.out
go tool cover -html=coverage.out
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Forwarded from Азбука айтишника
Микросервисы — это подход, при котором ваше приложение превращается в созвездие маленьких, независимых сервисов. Каждый живет своей жизнью, решает одну конкретную задачу и общается с «соседями» через API.
Где мы это видим на практике:
Онлайн-магазины: один сервис отвечает только за корзину, другой за оплату, третий «пинает» доставку. Если упала оплата, корзина всё еще работает.
Стриминги (Netflix/YouTube): каталог фильмов, система рекомендаций и сам плеер это разные микросервисы. Поэтому рекомендации могут «тупить», но фильм всё равно будет играть.
А что сейчас в вашем проекте?
❤️ — Уютный монолит (всё в одном месте, полёт нормальный)
🔥 — Микросервисный зоопарк
🔹 Практический интенсив «Архитектуры и шаблоны проектирования»
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib
#ликбез
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🔥2🥱2
sync.WaitGroupsync.WaitGroup содержит три поля: noCopy, state atomic.Uint64 и sema uint32.noCopy — маркер для go vet, запрещает копирование структуры после первого использования. В рантайме не занимает места.state — ключевое поле. В одном 64-битном слове упакованы два счётчика: старшие 32 бита — counter, количество незавершённых горутин, младшие 32 бита — waiter, количество горутин, заблокированных в Wait. Упаковка в одно слово нужна, чтобы атомарно обновлять оба значения за одну операцию и исключить гонку между Add и Wait.sema — системный семафор рантайма. Когда горутина вызывает Wait и counter > 0, она атомарно инкрементирует waiter и паркуется через runtime_Semacquire. Когда Add обнуляет counter, он делает runtime_Semrelease столько раз, сколько горутин ждёт.Done() — это просто Add(-1). Если после Add(delta) значение counter уходит в минус, рантайм паникует с "sync: negative WaitGroup counter".Please open Telegram to view this post
VIEW IN TELEGRAM
До 31 мая можно забрать любой курс Proglib Academy со скидкой 40%
Если давно хотели прокачаться в Python, ML, алгоритмах или AI-агентах, сейчас самое время выбрать программу и начать обучение по сниженной цене.
🎁 Разработка AI-агентов — от 49.000 ₽ (вместо 69.000 ₽)
Практический курс по разработке AI-агентов для автоматизации задач, работы и собственных проектов
🎁 Курс AgentOps — 129.000 ₽ (вместо 149.000 ₽)
Для разработчиков и LLM-инженеров, которые хотят внедрять AI-логику в бэкенд и сохранять стабильность сервиса.
🎁 Математика для разработки AI-моделей — 23.990 ₽ (вместо 31.990 ₽)
Практическая база по математике для анализа данных, ML и дальнейшего развития в AI.
🎁 Математика для Data Science — от 29.990 ₽ (вместо 39.990 ₽)
Курс для тех, кто хочет решать задачи, которые дают на собеседованиях на позицию дата-сайентиста в бигтехе.
🎁 ML для старта в Data Science — 28.990 ₽ (вместо 38.990 ₽)
Разберётесь в машинном обучении: от базовых понятий и линейных моделей до ансамблей, бустинга и рекомендательных систем.
🎁 Основы IT для непрограммистов — 16.990 ₽ (вместо 28.990 ₽)
Курс для IT-рекрутеров, маркетологов, проджектов, продактов и всех, кто работает с IT, но не пишет код.
🎁 Архитектуры и шаблоны проектирования — 27.990 ₽ (вместо 37.900 ₽)
Освоите основные паттерны проектирования и прокачаете навыки архитектора программного обеспечения.
🎁 Специалист по ИИ — 89.000 ₽ (вместо 113.900 ₽)
Курс для тех, кто хочет получить профессию в сфере ИИ, собрать портфолио из 5 проектов и научиться разрабатывать сложных AI-агентов.
🎁 Алгоритмы и структуры данных — 33.990 ₽ (вместо 57.990 ₽)
Подготовитесь к алгоритмическим собеседованиям, разберёте структуры данных и научитесь писать более эффективный код.
🎁 Программирование на языке Python — 27.990 ₽ (вместо 47.390 ₽)
Освоите Python на практике: без сухой теории, с пошаговой прокачкой навыков и итоговым проектом в портфолио.
🙌 Выбирайте курс по ссылке, оставляйте заявку, и менеджер поможет подобрать программу под ваши цели — https://clc.to/SALE40
Если давно хотели прокачаться в Python, ML, алгоритмах или AI-агентах, сейчас самое время выбрать программу и начать обучение по сниженной цене.
🎁 Разработка AI-агентов — от 49.000 ₽ (вместо 69.000 ₽)
Практический курс по разработке AI-агентов для автоматизации задач, работы и собственных проектов
🎁 Курс AgentOps — 129.000 ₽ (вместо 149.000 ₽)
Для разработчиков и LLM-инженеров, которые хотят внедрять AI-логику в бэкенд и сохранять стабильность сервиса.
🎁 Математика для разработки AI-моделей — 23.990 ₽ (вместо 31.990 ₽)
Практическая база по математике для анализа данных, ML и дальнейшего развития в AI.
🎁 Математика для Data Science — от 29.990 ₽ (вместо 39.990 ₽)
Курс для тех, кто хочет решать задачи, которые дают на собеседованиях на позицию дата-сайентиста в бигтехе.
🎁 ML для старта в Data Science — 28.990 ₽ (вместо 38.990 ₽)
Разберётесь в машинном обучении: от базовых понятий и линейных моделей до ансамблей, бустинга и рекомендательных систем.
🎁 Основы IT для непрограммистов — 16.990 ₽ (вместо 28.990 ₽)
Курс для IT-рекрутеров, маркетологов, проджектов, продактов и всех, кто работает с IT, но не пишет код.
🎁 Архитектуры и шаблоны проектирования — 27.990 ₽ (вместо 37.900 ₽)
Освоите основные паттерны проектирования и прокачаете навыки архитектора программного обеспечения.
🎁 Специалист по ИИ — 89.000 ₽ (вместо 113.900 ₽)
Курс для тех, кто хочет получить профессию в сфере ИИ, собрать портфолио из 5 проектов и научиться разрабатывать сложных AI-агентов.
🎁 Алгоритмы и структуры данных — 33.990 ₽ (вместо 57.990 ₽)
Подготовитесь к алгоритмическим собеседованиям, разберёте структуры данных и научитесь писать более эффективный код.
🎁 Программирование на языке Python — 27.990 ₽ (вместо 47.390 ₽)
Освоите Python на практике: без сухой теории, с пошаговой прокачкой навыков и итоговым проектом в портфолио.
🙌 Выбирайте курс по ссылке, оставляйте заявку, и менеджер поможет подобрать программу под ваши цели — https://clc.to/SALE40
signal.NotifyContext(ctx, signals...) и что возвращаетФункция принимает родительский контекст и список сигналов ОС, возвращает два значения: дочерний контекст и функцию
stop.Контекст отменяется автоматически, когда процесс получает один из перечисленных сигналов — например,
syscall.SIGINT (Ctrl+C) или syscall.SIGTERM. После отмены ctx.Err() вернёт context.Canceled, а ctx.Done() будет закрыт.Функция
stop останавливает перенаправление сигналов и освобождает внутренние ресурсы пакета signal. Её нужно обязательно вызвать — как правило, через defer stop() сразу после создания контекста.ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
<-ctx.Done()
fmt.Println("получен сигнал:", ctx.Err())
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
stop() после signal.NotifyContextВнутри пакета
signal ведётся реестр каналов, которым нужно доставлять сигналы. Пока stop не вызван, канал остаётся в этом реестре. Это означает две проблемы.Первая — утечка ресурсов: внутренний канал не будет собран GC, даже если контекст уже отменён и никто его не использует.
Вторая — поведенческая: если программа перехватывает тот же сигнал в нескольких местах, лишние подписчики продолжат получать события, что может приводить к неожиданному поведению.
Правило простое:
stop вызывается через defer сразу после создания контекста, независимо от того, был ли сигнал получен.ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT)
defer stop() // освобождает ресурсы в любом случае
Please open Telegram to view this post
VIEW IN TELEGRAM