CORS это тема, где легко допустить ошибку в конфигурации и не заметить этого. Разрешить все origins через
*, забыть проверить preflight, или написать паттерн, который пропускает лишнее. Библиотека jub0bs/cors построена так, чтобы минимизировать такие сценарии.Что это такое
jub0bs/cors — мидлвара для стандартного net/http, которая реализует CORS-протокол строго по спецификации Fetch standard. Автор позиционирует её как более безопасную альтернативу популярной rs/cors: API спроектирован так, что небезопасные конфигурации просто не дают себя создать.Как это работает
Создаём мидлвару через
cors.NewMiddleware, передаём конфиг, оборачиваем нужный ServeMux:package main
import (
"io"
"log"
"net/http"
"github.com/jub0bs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", handleHello) // CORS здесь не настроен
corsMw, err := cors.NewMiddleware(cors.Config{
Origins: []string{"https://example.com"},
Methods: []string{http.MethodGet, http.MethodPost},
RequestHeaders: []string{"Authorization"},
})
if err != nil {
log.Fatal(err) // плохая конфигурация — ошибка сразу, не в рантайме
}
corsMw.SetDebug(true) // включить debug-режим при разработке
api := http.NewServeMux()
api.HandleFunc("GET /users", handleUsersGet)
api.HandleFunc("POST /users", handleUsersPost)
mux.Handle("/api/", http.StripPrefix("/api", corsMw.Wrap(api)))
if err := http.ListenAndServe(":8080", mux); err != http.ErrServerClosed {
log.Fatal(err)
}
}
Маршрут
/hello не попадает под CORS — мы явно применяем мидлвару только к /api/. Это позволяет настраивать CORS точечно, а не на всё приложение сразу.Что выделяет библиотеку
Валидация конфига происходит при старте. Если что-то не так —
NewMiddleware возвращает ошибку сразу, не в момент обработки запроса. Никаких сюрпризов в продакшне.Есть debug-режим: при включённом
SetDebug(true) мидлвара добавляет в ответ заголовки с объяснением, почему preflight провалился. Это удобно при разработке и легко отключается в продакшне.Мидлвару можно перенастраивать на лету через метод
Reconfigure без перезапуска сервера. Это потокобезопасно.Ошибки конфигурации можно обрабатывать программно через пакет
cfgerrors — например, для формирования ответа в формате RFC 9457 (Problem Details).По бенчмаркам автора библиотека быстрее
rs/cors, хотя для большинства проектов это не принципиально.Чего библиотека не умеет
Она намеренно ограничена. Нельзя задать произвольный паттерн для origins — только конкретные значения из заранее определённого набора форматов. Нельзя логировать каждый запрос через мидлвару. Нельзя менять статус-код preflight-ответа (всегда 204). Автор объясняет эти ограничения соображениями безопасности и соответствия спецификации.
Строгий по умолчанию, с валидацией на старте, debug-режимом и возможностью перенастройки без рестарта.
📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2🔥2
Многие думают, что это просто линтер или code style. Но причина куда глубже и она спрятана в самом сердце компилятора, на уровне, до которого добираются немногие.
// Так написать не получится — будет ошибка компиляции
func foo()
{
fmt.Println("hello")
}
Подсказка:
Ответ:
📍 Навигация: Вакансии • Задачи • Собесы
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱6❤3👍2
🛠 CLI для PostgreSQL с автодополнением
Стандартный
Как подключиться
Несколько вариантов на выбор:
Установка:
Конфигурация
При первом запуске создаётся конфиг по пути
Стоит ли использовать вместо pgcli
В планах стриминг результатов для больших таблиц, экспорт в CSV, Excel и SQL, просмотр таблиц через браузер.
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoToProduction
Стандартный
psql работает, но не помогает. Нет подсветки синтаксиса, нет автодополнения ключевых слов, нет нормальной истории команд. Когда пишешь запросы вручную по памяти, то это замедляет работу.pgxcli это интерактивный CLI для PostgreSQL, написанный на Go. Он добавляет подсветку SQL прямо в терминале, автодополняет ключевые слова и команды, сохраняет историю сессий и поддерживает стандартные команды PostgreSQL: \d, \l, \dt, \q.Как подключиться
Несколько вариантов на выбор:
# Позиционные аргументы
pgxcli mydb myuser
# Флаги
pgxcli --host localhost --port 5432 --user postgres --dbname postgres
# URI
pgxcli postgres://user:password@localhost:5432/dbname
# Интерактивная форма подключения
pgxcli -i
Установка:
go install github.com/balaji01-4d/pgxcli/cmd/pgxcli@latest
Конфигурация
При первом запуске создаётся конфиг по пути
~/.config/pgxcli/config.toml. Там можно настроить стиль промпта и цветовую схему.Стоит ли использовать вместо pgcli
pgxcli пока молодой проект, версия v0.1.0 вышла в конце апреля 2026 года. Преимущество одно — это единый бинарник без внешних зависимостей с быстрым стартом.В планах стриминг результатов для больших таблиц, экспорт в CSV, Excel и SQL, просмотр таблиц через браузер.
📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10
🖇 Новый пакет для поддержки JIT-компиляторов и встроенных VM
В трекере Go появился proposal #78189. Он предлагает добавить стандартный пакет
В чём проблема
Go компилирует код заранее. Стек-анвайндер рантайма устроен так, что знает только о функциях, зарегистрированных в
Если на стеке оказывается счётчик команд из динамически сгенерированного кода — JIT-компилятора, WASM-рантайма или встроенной VM — рантайм падает с фатальной ошибкой:
Это затрагивает любую программу, которая встраивает JIT, например, база данных компилирует SQL в нативный код, хостит WASM, использует FFI с трамплинами или встраивает скриптовые VM вроде Lua.
Единственный обходной путь сегодня — не вызывать Go-функции из динамического кода вообще, либо использовать промежуточные C-фреймы через
Что предлагают
Новый пакет
Три режима анвайндинга:
Для кооперации со шедулером — функция
Как это работает внутри
Реестр регионов построен на copy-on-write с атомарным свапом указателя. Анвайндер получает доступ к нему без блокировок. Патчи в
Горутина остаётся в состоянии
Статус
Proposal открыт в марте 2026 года. Реализация около 500 строк кода, 15 тестов, трамплины для всех 13 Linux-архитектур. Проверена в продакшне в движке базы данных MemCP.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoLive
В трекере Go появился proposal #78189. Он предлагает добавить стандартный пакет
runtime/jit, который позволит Go-рантайму корректно работать с динамически генерируемым кодом.В чём проблема
Go компилирует код заранее. Стек-анвайндер рантайма устроен так, что знает только о функциях, зарегистрированных в
moduledata на этапе линковки. Если на стеке оказывается счётчик команд из динамически сгенерированного кода — JIT-компилятора, WASM-рантайма или встроенной VM — рантайм падает с фатальной ошибкой:
runtime: unexpected return pc for somefunc called from 0x7f4a12340010
fatal error: unknown caller pc
Это затрагивает любую программу, которая встраивает JIT, например, база данных компилирует SQL в нативный код, хостит WASM, использует FFI с трамплинами или встраивает скриптовые VM вроде Lua.
Единственный обходной путь сегодня — не вызывать Go-функции из динамического кода вообще, либо использовать промежуточные C-фреймы через
cgo, что добавляет около 40 наносекунд накладных расходов и требует cgo-тулчейна.Что предлагают
Новый пакет
runtime/jit с минимальным API. Ключевые части:Region — структура, описывающая регион исполняемой памяти. Содержит колбэки для анвайндинга (Next), описания фреймов в трейсбеке (Describe) и сканирования корней GC (ScanStack).Три режима анвайндинга:
UnwindStop — трейсбек обрывается на JIT-фреймеUnwindSkip — рантайм пропускает пользовательские фреймы и продолжаетUnwindDeclare — пропускает и описывает фреймы в трейсбеке.handle := jit.Register(jit.Region{
Lo: uintptr(codeStart),
Hi: uintptr(codeEnd),
Unwind: jit.UnwindDeclare,
Next: myUnwindNext,
Describe: myDescribe,
ScanStack: myScanStack,
})
defer handle.Unregister()Для кооперации со шедулером — функция
Preempt(). JIT-код вызывает её в точках безопасности (заголовки циклов, входы в функции) и возвращает управление Go, если шедулер или GC запросили остановку.Как это работает внутри
Реестр регионов построен на copy-on-write с атомарным свапом указателя. Анвайндер получает доступ к нему без блокировок. Патчи в
traceback.go проверяют пользовательские регионы перед тем, как бросить ошибку на неизвестный счётчик команд. GC получает хук в markroot() для вызова ScanStack.Горутина остаётся в состоянии
_Grunning пока выполняется JIT-код — никакого переключения состояний, никакого освобождения. Это принципиальное отличие от cgocall, который обращается с чужим кодом как с чёрным ящиком.Статус
Proposal открыт в марте 2026 года. Реализация около 500 строк кода, 15 тестов, трамплины для всех 13 Linux-архитектур. Проверена в продакшне в движке базы данных MemCP.
📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4👾1
Мир, труд, май!
— GopherCon 2026
— Конец накрутки опыта
— Скоро Go заморозят
— CORS-мидлвар, который сложно настроить неправильно
📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
Сбер тестирует кандидатов по архетипам Маат, Исиды и Бастет. Яндекс ввёл обязательный fit-интервью и единую систему оценки. А ГигаРекрутер в Telegram уже проводит первичные интервью вместо живого HR.
Что реально происходит на рынке IT-найма и как к этому готовиться
📍 Навигация: Вакансии • Задачи • Собесы
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👾3😁2
Стандартная библиотека
encoding/json в Go работает медленно на больших объёмах данных. Если сервис обрабатывает тысячи запросов в секунду с тяжёлыми JSON-структурами, это становится заметным узким местом.Sonic это библиотека для сериализации и десериализации JSON, которая использует JIT-компиляцию и SIMD-инструкции процессора. Она полностью совместима с API
encoding/json, то есть замена происходит в одну строку.Что под капотом
Sonic генерирует машинный код под конкретную схему данных прямо во время выполнения, а не в момент компиляции. SIMD позволяет обрабатывать несколько байт одновременно на уровне железа.
В итоге на средних JSON (13 КБ, 300+ ключей) скорость кодирования достигает 2468 МБ/с против 792 МБ/с у стандартной библиотеки.
Установка:
go get github.com/bytedance/sonic
Базовое использование
Замена
encoding/json буквально в одну строку:import "github.com/bytedance/sonic"
var data YourSchema
// Кодирование
output, err := sonic.Marshal(&data)
// Декодирование
err := sonic.Unmarshal(output, &data)
Стриминг
Sonic поддерживает потоковое чтение из
io.Reader и запись в io.Writer:var o = map[string]interface{}{}
var r = strings.NewReader(`{"a":"b"}{"1":"2"}`)
var dec = sonic.ConfigDefault.NewDecoder(r)
dec.Decode(&o)
dec.Decode(&o)
fmt.Printf("%+v", o)
// map[1:2 a:b]Частичный парсинг через ast.Node
Если нужно вытащить одно поле из большого JSON, не парся всё целиком:
import "github.com/bytedance/sonic"
node, err := sonic.GetFromString(twitterJson, "statuses", 3, "user")
var user User
err = sonic.UnmarshalString(node.Raw(), &user)
Pretouch для тяжёлых схем
Sonic компилирует код при первом вызове. Если схема большая, первый запрос может подвиснуть.
Чтобы этого избежать, компилируем заранее при старте приложения:
import (
"reflect"
"github.com/bytedance/sonic"
)
func init() {
var v HugeStruct
err := sonic.Pretouch(reflect.TypeOf(v))
}
Готовые конфиги
•
sonic.ConfigDefault — быстрый режим по умолчанию•
sonic.ConfigStd — совместимый со стандартной библиотекой•
sonic.ConfigFastest — максимальная скорость, без дополнительных проверокНа платформах без поддержки JIT Sonic автоматически откатывается к
encoding/json.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍9🔥3
🦾 Почему ваши AI-продукты на базе LLM ломаются (и как это чинить)?
Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало».
🗓️ Когда: 14 мая в 19:00 МСК
⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы
🧑🏻💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы.
🎁 Главный бонус для онлайна:
Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps.
👉 Занять место на вебинаре
Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало».
🗓️ Когда: 14 мая в 19:00 МСК
⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы
🧑🏻💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы.
🎁 Главный бонус для онлайна:
Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps.
👉 Занять место на вебинаре
🥱4👍1
🔄 oapi-codegen v2.7.0
Вышел релиз
Три изменения, которые затронут существующий код
1. Strict-server с внешними
Если strict-server использует внешний
Добавьте в конфиг источника:
2. Переименование анонимных схем
Анонимные схемы внутри
3. Инлайн middleware-типы в strict-server
Теперь они определяются прямо в сгенерированном коде:
Если вы ссылались на типы вида
Что нового
Разрешение коллизий имён. Новая опция
Коллизия разрешается детерминированно через суффикс:
Опция отключена по умолчанию.
Полная матрица параметров. Теперь поддерживаются все комбинации
Опциональные заголовки ответов. В strict-server необязательные заголовки теперь генерируются как указатели. Если поле
Старое поведение возвращается через
Echo v5. Добавлена поддержка Echo v5 через флаг
Middleware на уровне операций в Echo. В
Middleware на уровне хендлеров в Fiber. В
Обработчики ошибок в strict-server для Gin. Теперь Gin поддерживает
Требования к окружению
Для сборки и запуска
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoLive
Вышел релиз
oapi-codegen v2.7.0. Это Go-инструмент, который генерирует серверный и клиентский код из OpenAPI-спецификаций. Версия исправляет проблемы с allOf/anyOf/oneOf, внешними $ref, перечислениями и обходом схем.Три изменения, которые затронут существующий код
1. Strict-server с внешними
$ref на ответыЕсли strict-server использует внешний
$ref на components/responses/... из другой спецификации, эта спецификация теперь тоже должна генерироваться с strict-server: true. Добавьте в конфиг источника:
generate:
models: true
strict-server: true
2. Переименование анонимных схем
Анонимные схемы внутри
oneOf, anyOf и additionalProperties теперь генерируются по единому шаблону:GetPets_200_Data_Item → GetPets200JSONResponseBody_Data_Item
GetPets200JSONResponse_Data_Item → GetPets200JSONResponseBody_Data_Item
3. Инлайн middleware-типы в strict-server
StrictHandlerFunc и StrictMiddlewareFunc больше не являются алиасами к типам из пакета runtime/strictmiddleware/<framework>. Теперь они определяются прямо в сгенерированном коде:
// было
import strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc
// стало
type StrictHandlerFunc func(ctx echo.Context, request any) (any, error)
Если вы ссылались на типы вида
strictecho.StrictEchoHandlerFunc напрямую, замените их на StrictHandlerFunc из сгенерированного пакета.Что нового
Разрешение коллизий имён. Новая опция
output-options.resolve-type-name-collisions: true позволяет генерировать код, когда два разных определения претендуют на одинаковое Go-имя. Коллизия разрешается детерминированно через суффикс:
type Status string // из components.schemas.Status
type StatusParameter = string // из components.parameters.Status
Опция отключена по умолчанию.
Полная матрица параметров. Теперь поддерживаются все комбинации
style × explode × type для параметров пути, запроса, заголовков и куки. Если раньше падала ошибка unsupported style или поведение отличалось в разных бэкендах, регенерация должна это исправить. Требуется github.com/oapi-codegen/runtime версии v1.4.0 или выше.Опциональные заголовки ответов. В strict-server необязательные заголовки теперь генерируются как указатели. Если поле
nil, заголовок не отправляется:// было
type GetFoo200ResponseHeaders struct {
XOptional string // всегда в ответе, даже пустым
}
// стало
type GetFoo200ResponseHeaders struct {
XOptional *string // nil — заголовок не отправляется
}
Старое поведение возвращается через
compatibility.headers-implicitly-required: true.Echo v5. Добавлена поддержка Echo v5 через флаг
generate.echo5-server: true. Echo v4 не затронут.Middleware на уровне операций в Echo. В
RegisterHandlersWithOptions появился OperationMiddlewares:api.RegisterHandlersWithOptions(e, server, api.RegisterHandlersOptions{
OperationMiddlewares: map[string][]echo.MiddlewareFunc{
"createPet": {authMiddleware, auditMiddleware},
},
})Middleware на уровне хендлеров в Fiber. В
FiberServerOptions появился слайс HandlerMiddlewares []HandlerMiddlewareFunc.Обработчики ошибок в strict-server для Gin. Теперь Gin поддерживает
RequestErrorHandlerFunc и ResponseErrorHandlerFunc в StrictServerOptions, как это уже было в Echo.Требования к окружению
Для сборки и запуска
oapi-codegen теперь нужен Go 1.24.4+. Сгенерированный код по-прежнему может работать на более старых версиях. Из-за транзитивных зависимостей может потребоваться зафиксировать версии:github.com/speakeasy-api/jsonpath v0.6.3
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936
📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2🤩2🔥1👾1
Вы настроили SSH-туннель, отошли на час, вернулись, а соединение упало. Поднимаете снова вручную. Через день история повторяется. Если туннелей несколько, это превращается в рутину.
boring решает именно это. Он держит туннели живыми, переподключает их автоматически и управляет всем через один TOML-файл.Что умеет
Поддерживает три режима проброса портов: локальный, удалённый и динамический через SOCKS5. Работает с
~/.ssh/config и ssh-agent, если хост уже описан там, достаточно указать его имя. Умеет работать с Unix-сокетами. Есть автодополнение для bash, zsh и fish.Бинарник появится в папке
dist. Его нужно переложить в любую директорию из $PATH.Пример конфига с двумя туннелями:
# туннель к dev-серверу, хост берётся из SSH config
[[tunnels]]
name = "dev"
local = "9000"
remote = "localhost:9000"
host = "dev-server"
# туннель к prod с явными параметрами
[[tunnels]]
name = "prod"
local = "5001"
remote = "localhost:5001"
host = "prod.example.com"
user = "root"
identity = "~/.ssh/id_prod"
Каждый туннель описывается несколькими полями. Обязательные:
name, local, remote, host. Остальное опционально, boring подтянет нужное из SSH config или использует значения по умолчанию.Основные команды:
boring list # показать все туннели
boring open dev # открыть туннель по имени
boring open -a # открыть все туннели сразу
boring close dev # закрыть туннель
boring edit # открыть файл конфигурации
Поддерживаются glob-паттерны. Можно открыть сразу несколько туннелей командой вида
boring open prod*.Keep-alive
По умолчанию
boring отправляет keep-alive каждые 120 секунд. Значение можно переопределить глобально или на уровне конкретного туннеля:keep_alive = 60 # в секундах
[[tunnels]]
name = "flaky-server"
keep_alive = 30
...
boring не требует демона, не тянет зависимостей и не лезет в системные настройки. Один бинарник, один TOML-файл и туннели просто работают в фоне.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3👾1
🍵 Почтовый клиент прямо в терминале
Каждый раз, когда нужно проверить почту, вы переключаетесь в браузер, ждёте загрузки, отвечаете на письмо и возвращаетесь обратно. Если большую часть дня вы проводите в терминале, это раздражает.
Что умеет
Читать и отправлять письма, отвечать с цитированием, скачивать вложения, искать по входящим. Поддерживает Gmail, iCloud и любой кастомный IMAP/SMTP.
Если пишете письмо в Markdown клиент сам конвертирует его в HTML перед отправкой. Черновики сохраняются автоматически при выходе из редактора.
Навигация в стиле Vim:
Настройка
При первом запуске клиент попросит указать email, пароль и провайдера. Конфиг хранится в
Важно знать: пароли хранятся в конфиге в открытом виде. Авторы сами об этом предупреждают.
Если терминал это ваша основная рабочая среда,
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoToProduction
Каждый раз, когда нужно проверить почту, вы переключаетесь в браузер, ждёте загрузки, отвечаете на письмо и возвращаетесь обратно. Если большую часть дня вы проводите в терминале, это раздражает.
matcha это TUI-клиент для работы с email, написанный на Go с использованием библиотеки Bubble Tea. Работает прямо в консоли, поддерживает несколько аккаунтов, вложения, черновики и даже отображение изображений в письмах, если терминал это позволяет.Что умеет
Читать и отправлять письма, отвечать с цитированием, скачивать вложения, искать по входящим. Поддерживает Gmail, iCloud и любой кастомный IMAP/SMTP.
Если пишете письмо в Markdown клиент сам конвертирует его в HTML перед отправкой. Черновики сохраняются автоматически при выходе из редактора.
Навигация в стиле Vim:
j/k для движения по списку, r для обновления входящих, / для поиска, d для удаления.Настройка
При первом запуске клиент попросит указать email, пароль и провайдера. Конфиг хранится в
~/.config/matcha/config.json. Для Gmail и iCloud нужен app-specific password, обычный пароль от аккаунта не подойдёт.Важно знать: пароли хранятся в конфиге в открытом виде. Авторы сами об этом предупреждают.
Если терминал это ваша основная рабочая среда,
matcha позволяет не выходить из неё ради почты.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
surf — продвинутый HTTP-клиент для Go. Он поддерживает имитацию браузерных отпечатков, HTTP/2 и HTTP/3, сессии, middleware, стриминг и многое другое.Зачем это нужно
Стандартный
net/http выдаёт себя по TLS-отпечатку. Большинство защищённых сайтов различают настоящий браузер и скрипт именно по нему. surf эмулирует не только заголовки, но и низкоуровневые параметры TLS-рукопожатия, порядок заголовков и настройки QUIC.Как это работает
Простой GET-запрос выглядит так:
resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
if resp.IsErr() {
log.Fatal(resp.Err())
}
fmt.Println(resp.Ok().Body.String().Unwrap())Имитация Chrome с сессией:
client := surf.NewClient().
Builder().
Impersonate().Chrome().
Session().
Build().
Unwrap()
resp := client.Get("https://example.com").Do()
Firefox со случайной ОС:
client := surf.NewClient().
Builder().
Impersonate().
RandomOS().
Firefox().
Build().
Unwrap()
HTTP/3 с полным QUIC-отпечатком:
client := surf.NewClient().
Builder().
Impersonate().Chrome().
ForceHTTP3().
Build().
Unwrap()
resp := client.Get("https://cloudflare-quic.com/").Do()
fmt.Println(resp.Ok().Proto) // HTTP/3.0
Декодирование JSON-ответа:
type User struct {
Name string `json:"name"`
Company string `json:"company"`
}
resp := surf.NewClient().Get("https://api.github.com/users/github").Do()
if resp.IsOk() {
var user User
resp.Ok().Body.JSON(&user)
}Middleware для логирования:
client := surf.NewClient().
Builder().
With(func(resp *surf.Response) error {
fmt.Printf("статус: %d, время: %v\n", resp.StatusCode, resp.Time)
return nil
}).
Build().
Unwrap()
Что ещё умеет
• поддерживает прокси SOCKS5 с UDP для HTTP/3, DNS-over-TLS
• привязку к сетевому интерфейсу
• Unix-сокеты
• кэширование тела ответа
• стриминг, Server-Sent Events
Клиент совместим со стандартным
net/http через метод Std() — это позволяет использовать его с любыми сторонними библиотеками, ожидающими *http.Client.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍9👾2
Golang-разработчик (eHealth) — до 200 000 ₽, удаленно по Москве
Middle+ Software Engineer — удаленно + помогут с переездом
Tech Lead / Senior Backend Developer (Golang) — до 4 000 $ , удалёнка вне РФ и РБ
#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
📘 На новой платформе Mentorix вышел курс — «Golang: микросервисная архитектура и проектирование API»
Уже пишете на Go и хотите вырасти из «закрыть тикет ручкой» в архитектора распределённых систем? Этот курс — именно про инженерию: как спроектировать API, развернуть и держать в продакшене десяток сервисов, которые не падают под нагрузкой.
• Полный стек: HTTP/REST, gRPC, RabbitMQ и Kafka, PostgreSQL, Redis, Docker, Kubernetes, Prometheus + Grafana
• 200+ интерактивных заданий с автопроверкой — пишете код прямо в браузере, в любое удобное время
• Финальный проект: рабочая микросервисная экосистема, которую кладёте в портфолио и показываете на собесе
🎓 Сертификат по завершении — добавьте его в резюме или профиль LinkedIn
Скидка 40% — действует 48 часов
🚀 Прокачайте Go и выйдите на уровень мидл/сеньор-разработчика микросервисов. Начните сегодня — следующая неделя будет уже с новыми навыками.
👉 Пройти курс на Mentorix
Уже пишете на Go и хотите вырасти из «закрыть тикет ручкой» в архитектора распределённых систем? Этот курс — именно про инженерию: как спроектировать API, развернуть и держать в продакшене десяток сервисов, которые не падают под нагрузкой.
• Полный стек: HTTP/REST, gRPC, RabbitMQ и Kafka, PostgreSQL, Redis, Docker, Kubernetes, Prometheus + Grafana
• 200+ интерактивных заданий с автопроверкой — пишете код прямо в браузере, в любое удобное время
• Финальный проект: рабочая микросервисная экосистема, которую кладёте в портфолио и показываете на собесе
🎓 Сертификат по завершении — добавьте его в резюме или профиль LinkedIn
Скидка 40% — действует 48 часов
🚀 Прокачайте Go и выйдите на уровень мидл/сеньор-разработчика микросервисов. Начните сегодня — следующая неделя будет уже с новыми навыками.
👉 Пройти курс на Mentorix
❤1
Оба инструмента отменяют изменения, но делают это по-разному. Путаница между ними приводит к потере коммитов или конфликтам в общей ветке.
Что делает git reset
git reset перемещает указатель ветки назад. Он буквально переписывает историю коммитов — те коммиты, которые были после указанной точки, исчезают.Три режима работы:
•
git reset --soft HEAD~1 — отменяет коммит, но сохраняет изменения в индексе. Файлы готовы к новому коммиту.•
git reset --mixed HEAD~1 — отменяет коммит и убирает файлы из индекса. Изменения остаются в рабочей директории. Это режим по умолчанию.•
git reset --hard HEAD~1 — удаляет коммит и все изменения без возможности восстановления.Пример: написали коммит с опечаткой в сообщении или забыли добавить файл.
git reset --soft HEAD~1
git add forgotten-file.js
git commit -m "правильное сообщение"
Что делает git revert
git revert создаёт новый коммит, который отменяет изменения из указанного коммита. История не переписывается — в ней появляется дополнительная запись об отмене.git revert a1b2c3d
Git создаст коммит вида
Revert "название вашего коммита". В нём будут обратные изменения — то, что было добавлено, удалится, и наоборот.Если нужно отменить несколько коммитов подряд:
git revert HEAD~3..HEAD
В чём принципиальная разница
git reset меняет историю. Если вы уже отправили ветку на сервер и потом сделали reset, вам придётся делать git push --force. Это создаёт проблемы для всех, кто работает с этой веткой — их локальные копии окажутся не синхронизированы с удалённой.git revert историю не трогает. Новый коммит просто добавляется поверх. Это безопасно для общих веток.Как выбрать
Работаете в локальной ветке, которую ещё не пушили — используйте
git reset. Он чище, не засоряет историю лишними коммитами.Нужно отменить изменения в ветке, с которой работает команда — только
git revert. Даже если очень хочется сделать reset и force push, это плохая идея.Что делать, если всё сломалось
Если случайно сделали
git reset --hard и потеряли коммиты — не паникуйте. Git хранит ссылки на все объекты в reflog ещё 30 дней.git reflog
git reset --hard HEAD@{2}
reflog покажет историю всех перемещений HEAD. Найдите нужный коммит и восстановитесь на него.git reset — для локальной правки истории до того, как она ушла на сервер. git revert — для безопасной отмены в общих ветках. Правило простое: если ветка уже запушена и её видят другие, используйте revert.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7