TGViewer
Channel Public Channel
Библиотека Go-разработчика | Golang

Библиотека Go-разработчика | Golang

@goproglib

Все самое полезное для Go-разработчика в одном канале.

Учиться у нас: clc.to/qaSdww

По рекламе: @tproger_sales_bot

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0

Заявка: 8137752389
Subscribers
24.1K
Photos
2.8K
Videos
54
Links
5.4K

Showing posts older than #7221 · Back to latest

Older Posts 14 shown
Post #7220 3.19K
😎 Топ-вакансий для Go-разработчиков за неделю

Golang-разработчик — от 220 000 до 250 000 ₽, удаленно по Москве

Go-разработчик — офис/гибрид в Москве

Software Golang Engineer — удалённо in english.

➡️ Еще больше топовых вакансий — в нашем канале Go jobs

🐸 Библиотека Go-разработчика

#GoWork
  • 🔥 2
  • 👏 2
Post #7219 3.12K
⚡️ Ленивый Map через iter.Seq

Map на новом слайсе пишется за минуту — все его видели:
func Map[T, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = fn(v)
}
return result
}


Работает. Просто. Но всегда выделяет новый слайс, даже если результат сразу пойдёт в следующую трансформацию.

Как использовать iter.Seq

С Go 1.23 Map можно написать иначе — возвращать не слайс, а итератор:
func Map[A, B any](seq iter.Seq[A], f func(A) B) iter.Seq[B] {
return func(yield func(B) bool) {
for v := range seq {
if !yield(f(v)) {
return
}
}
}
}


Функция возвращает замыкание, которое будет вызываться по требованию.

Пример:
numbers := slices.Values([]int{1, 2, 3, 4, 5})

result := slices.Collect(
Map(
Map(numbers, func(n int) int { return n * 2 }),
func(n int) int { return n + 10 },
),
)
// [12, 14, 16, 18, 20]


Два Map подряд — один проход по данным, одна аллокация на Collect. Промежуточного слайса нет.

Нюансы

iter.Seq, slices.Values и slices.Collect — всё это Go 1.23+.

Fluent-чейнинга seq.Map(f).Map(g) не будет — в Go нельзя навесить дженерик-метод на произвольный тип. Живём с вложенными вызовами.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • ❤ 6
  • 👍 4
  • 🎉 3
  • 👾 2
Post #7218 3.09K
🌐 h2c в Go 1.24+. HTTP/2 без TLS стало проще

Если вы запускаете Go-сервис в Google Cloud Run и используете долгоживущие соединения, у HTTP/1.1 есть известная проблема. Cloud Run не пробрасывает разрыв клиентского соединения на бэкенд. Сервер продолжает держать мёртвое соединение открытым, пока не истечёт таймаут. Решение — перейти на HTTP/2 cleartext (h2c).

Cloud Run сам терминирует TLS на фронтенде, а трафик до контейнера отправляет без шифрования. Можно выбрать HTTP/1.1 или h2c. Это тот самый режим «HTTP/2 with Prior Knowledge» из RFC 9113 (секция 3.3), когда клиент и сервер договариваются об HTTP/2 заранее, без Upgrade.

Как было до Go 1.24

Нужен был пакет golang.org/x/net/http2/h2c. Хендлер оборачивался в обёртку, потом отдельно конфигурировался http2.Server.

Выглядело громоздко:
import (
"net/http"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)

h2s := &http2.Server{}
handler = h2c.NewHandler(handler, h2s)
srv := &http.Server{
Addr: ":9888",
Handler: handler,
}
err = http2.ConfigureServer(srv, h2s)


Внешняя зависимость, неочевидный порядок вызовов, лишний бойлерплейт.

Как стало в Go 1.24+

Теперь всё настраивается через стандартный http.Server. Никаких обёрток и внешних пакетов:
srv := &http.Server{
Addr: ":9888",
Handler: handler,
}
srv.Protocols = new(http.Protocols)
srv.Protocols.SetHTTP1(true)
srv.Protocols.SetUnencryptedHTTP2(true)


Три строки вместо цепочки из обёртки, конфигурации и внешней зависимости. Сервер теперь принимает и HTTP/1.1, и h2c одновременно.

Проверка локально:
curl -i --http2-prior-knowledge http://localhost:9888


Если h2c не настроен, curl вернёт ошибку.

Конфигурация Cloud Run через Terraform

В описании контейнера порт нужно назвать h2c. Это сигнал для Cloud Run использовать HTTP/2 cleartext:
resource "google_cloud_run_v2_service" "api" {
name = "api"
location = var.primary_region

template {
containers {
ports {
name = "h2c"
container_port = 9888
}
}
max_instance_request_concurrency = 200
timeout = "900s"
}
}


На стороне балансировщика ничего менять не нужно. Serverless NEG сам корректно апгрейдит соединение до HTTP/2 при общении с Cloud Run.

Go 1.24 убрал главное неудобство h2c — зависимость от x/net/http2/h2c и запутанную конфигурацию. Если вы работаете с Cloud Run и SSE или gRPC, или любыми долгоживущими соединениями, переход на h2c решает проблему с зависшими коннектами и настраивается за минуту.

➡️ Источник

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • ❤ 8
Post #7217 3.3K
👨‍💻 Бест-практисы юнит-тестов в Go

Пакет testing в Go покрывает большинство задач без сторонних библиотек. Но сам по себе инструмент не гарантирует качество тестов. Ниже собраны практики, которые помогают писать тесты понятнее, надёжнее и проще в поддержке.

1. Пишите table-driven тесты

Это идиоматический подход в Go. Все сценарии описываются в слайсе структур и прогоняются в цикле через t.Run. Добавить новый кейс — одна строка. Сразу видно, что покрыто, а что нет:
tests := []struct {
name string
input int
expected int
wantErr bool
}{
{"positive", 5, 25, false},
{"zero", 0, 0, false},
{"negative", -1, 0, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := Square(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
}
if result != tt.expected {
t.Errorf("got %d, want %d", result, tt.expected)
}
})
}


2. Используйте t.Run для подтестов

Подтесты позволяют запускать конкретный сценарий по имени. Это экономит время при отладке, когда не нужно гонять весь набор:
go test -run TestSquare/negative


3. Помечайте хелперы через t.Helper()

Без t.Helper() стек ошибки укажет на строку внутри хелпера. С ним — на строку вызова в тесте:
func assertEqual(t *testing.T, got, want int) {
t.Helper()
if got != want {
t.Errorf("got %d, want %d", got, want)
}
}


4. Мокайте зависимости через интерфейсы

Определяете интерфейс, в проде подставляете реальную реализацию, в тестах — мок:
type Storage interface {
Get(id int) (*Item, error)
}

type MockStorage struct {
items map[int]*Item
}

func (m *MockStorage) Get(id int) (*Item, error) {
if item, ok := m.items[id]; ok {
return item, nil
}
return nil, errors.New("not found")
}


5. Тестируйте поведение, а не реализацию

Если тест ломается при рефакторинге внутренней логики без изменения внешнего контракта — это плохой тест. Начинайте с покрытия экспортируемых функций. Один тест проверяет одну вещь.

6. Давайте тестам понятные имена

Имя теста должно описывать сценарий и ожидаемый результат. При падении вы должны понять, что сломалось, не открывая код.

7. Запускайте тесты с флагом -race

Детектор гонок ловит проблемы конкурентного доступа, которые почти невозможно найти вручную.
go test -race ./...


8. Не гонитесь за 100% покрытия

Высокий процент не гарантирует отсутствие багов. Покрывайте критическую логику и граничные случаи. Качество тестов важнее количества.

9. Используйте TestMain для дорогого setup

Если подготовка окружения занимает время, вынесите её в TestMain. Она запускается один раз на весь пакет, а не перед каждым тестом:
func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}


10. Выбирайте инструменты под задачу

Стандартного testing хватает для большинства случаев. testify добавляет удобные ассерты и моки. httptest закрывает тестирование HTTP-хендлеров. testcontainers-go помогает с интеграционными тестами через Docker. Не тащите лишнего.

➡️ Нашу рассылку тестировать не нужно, её нужно читать

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • ❤ 12
  • 👍 11
Post #7216 3.01K
⚡️ SIMD-ускорение для слайсов в Go без unsafe и CGo

Go отлично справляется с циклами. Компилятор умеет автовекторизировать простые паттерны, и на современных процессорах с AVX-512 стандартный for range работает быстро. Но не для всех операций. Сравнения: min, max, count; компилятор векторизирует хуже, и на больших массивах это заметно. TurboSlice закрывает именно эту нишу.

turboslice — Go-библиотека, которая заменяет ручные циклы по слайсам на вызовы с SIMD-ускорением через 128-битные SSE-инструкции. Построена на пакете simd/archsimd из Go 1.26. Работает на любой платформе, но ускорение даёт на AMD64. На ARM64 и остальных архитектурах автоматически откатывается на скалярную реализацию.

Без CGo, без ассемблерных файлов, без unsafe в публичном API.

Что умеет

Агрегации (Sum, Min, Max, MinMax), поиск (Find, Contains, Count), поэлементная математика (AddSlices, MulSlices, DotProduct), а также набор дженерик-утилит (Map, Filter, Reduce, Chunk, Unique, Flatten и другие).

Когда SIMD помогает, а когда нет

Авторы честно описывают границы применимости. Реальный выигрыш от SSE получают Min, Max, MinMax, Count — от 2x до 2.6x на всех размерах. Для Sum и DotProduct[int32/float32] SIMD включается только на слайсах от 4K и 16K элементов соответственно. Ниже этих порогов накладные расходы на настройку SIMD съедают всю выгоду.

А вот Find, Contains, DotProduct[float64] и AddSlices[float64] остаются скалярными даже в SIMD-сборке. Компилятор Go на этих паттернах генерирует код лучше, чем ручной SSE. Для 64-битных целых умножений (MulSlices[int64], DotProduct[int64]) SSE/AVX2 просто не имеют нужной инструкции.

Нужен Go 1.26+. Для SIMD-ускорения собираем с флагом:
GOEXPERIMENT=simd go build ./...


Пример использования:
import "github.com/atul-007/turboslice"

data := []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

turboslice.Sum(data) // 55
turboslice.Find(data, 7) // 6
turboslice.Min(data) // 1
turboslice.Max(data) // 10
turboslice.Contains(data, 5) // true


Вместо типичного цикла:
total := 0
for _, v := range data {
total += v
}


Пишем одну строку:
total := turboslice.Sum(data)


Typed API для горячих путей

Если тип известен заранее и нужна максимальная производительность, есть типизированные функции (SumInt32, MinFloat64, CountInt32 и т.д.). Они инлайнятся без прохода через interface{} или type switch. На скалярной сборке работают наравне с ручным циклом, на SIMD-сборке получают ускорение.

turboslice.SumInt32(data)    // инлайнится напрямую
turboslice.MinFloat64(vals) // без диспатча через интерфейс


Пример из практики

Обработка сигналов:
signal  := loadSensorData()
weights := precomputeWeights(len(signal))

weighted := turboslice.MulSlices(signal, weights)
energy := turboslice.DotProduct(signal, signal)
lo, hi := turboslice.MinMax(signal)


Аналитический пайплайн:
scores := fetchAllScores() // []int32, миллионы записей

total := turboslice.Sum(scores)
lo, hi := turboslice.MinMax(scores)
outliers := turboslice.Filter(scores, func(s int32) bool {
return s > 3*stddev
})


Что стоит учесть

Min, Max, MinMax паникуют на пустых слайсах, как и slices.Min/Max из стандартной библиотеки. AddSlices, MulSlices, DotProduct молча обрезают до минимальной длины. Переполнение целых чисел не проверяется. Обработка NaN различается между SIMD и скалярной реализацией для Min/Max.

TurboSlice — нишевый инструмент. Если вы работаете с числовыми слайсами от десятков тысяч элементов на AMD64 и ваш bottleneck — агрегации типа min/max/count, библиотека даёт ощутимый прирост без компромиссов в безопасности кода. Для мелких слайсов и операций, где компилятор уже справляется, она просто не мешает.

➡️ Репозиторий

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 🔥 7
  • ❤ 3
Post #7215 2.84K
🆚 Git merge и rebase. В чём разница и когда что использовать

Обе команды решают одну задачу — подтянуть изменения из одной ветки в другую. Но делают это совершенно по-разному. Понимание этой разницы убирает половину путаницы при работе с ветками.

Ситуация

Вы работаете в feature-ветке. Пока вы пишете код, кто-то вливает новые коммиты в main. Ваша ветка отстала. Нужно обновиться.

Тут два варианта. Первый — git merge main. Второй — git rebase main. Оба подтянут свежие изменения, но история коммитов будет выглядеть по-разному.

Что делает merge

Merge берёт изменения из обеих веток и объединяет их в один новый коммит. Этот коммит называется merge commit:
git checkout feature
git merge main


Git создаёт точку слияния, где обе линии разработки сходятся. История сохраняется как есть — видно, когда ветки разошлись и когда соединились.

Это безопасный вариант. Ничего не перезаписывается, старые коммиты остаются на месте. Для новичков merge проще, потому что конфликты решаются один раз.

Минус проявляется на больших проектах. Когда разработчиков много, лог засоряется merge-коммитами вида «Merge branch 'main' into feature». Через пару месяцев читать такую историю становится тяжело.

Что делает rebase

Rebase переносит ваши коммиты поверх последнего состояния целевой ветки. Вместо объединения историй он перестраивает вашу ветку так, будто вы начали работу с самой свежей версии main:
git checkout feature
git rebase main


Git временно снимает ваши коммиты, обновляет ветку до актуального main, а потом накатывает ваши коммиты по одному заново. При этом коммиты пересоздаются — у них меняются хеши. Коммит C становится C', F становится F'. Именно поэтому говорят, что rebase переписывает историю.

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

Главное правило rebase

Не делайте rebase на ветках, с которыми работают другие люди. Rebase переписывает коммиты, и если кто-то уже забрал старые версии, возникнет каша из конфликтов.

Безопасно — rebase своей локальной feature-ветки. Опасно — rebase общей ветки, в которую пушат несколько человек.

Конфликты

Обе команды могут вызвать конфликты. Разница в том, как вы их решаете. При merge конфликт обычно один — в момент слияния. При rebase Git может останавливаться на каждом переносимом коммите. Это чуть утомительнее, но итоговая история получается чище.

Что используют на практике

Многие команды комбинируют оба подхода. Типичная схема выглядит так. Локально вы делаете git rebase main на своей feature-ветке, чтобы держать историю чистой. А когда feature готова, вливаете её в main через git merge или pull request.

Такой подход даёт чистую историю в feature-ветке и безопасное слияние в общую.

Merge сохраняет полную картину — кто, когда и откуда вливал изменения. Rebase делает историю линейной и читаемой. Ни один из подходов не лучше другого в абсолюте. Выбор зависит от того, что важнее вашей команде — полнота истории или её чистота.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 👍 6
  • ❤ 3
Post #7214 2.75K
До 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/U79QHw
Post #7213 3.28K
👨‍💻 Скрытая цена чрезмерной абстракции в Go

Интерфейсы повсюду, многослойные пакеты, DI-контейнеры, generic-репозитории. Код выглядит солидно на ревью. Но стоит починить баг, и вы проходите шесть слоёв абстракции ради пяти строк логики. В Go это обходится дороже, чем кажется.

Почему это происходит

Интерфейсы в Go не требуют implements, любой тип удовлетворяет им неявно. Это удобно, но создаёт ловушку. Интерфейсы легко определять, поэтому их определяют слишком много. Пакеты легко создавать, поэтому кодовая база обрастает слоями ради диаграммы, а не ради задачи.

Чем это бьёт

Вы видите s.repo.Find(ctx, query.NewUserQuery().WithID(id)) и не знаете, это база, кэш или мок. Индирекция без пользы, просто шум. Интерфейсы создаются под единственную реализацию ещё до первого теста. Тесты обрастают моками для моков. Файл теста длиннее кода, который он тестирует.

Как оставаться простыми

Начинайте с конкретики. Напишите структуру, заставьте работать. Интерфейс выносите, когда появится вторая реализация. Так устроена стандартная библиотека Go. io.Reader не определили заранее:
type UserStore struct {
db *sql.DB
}

func (s *UserStore) GetByID(ctx context.Context, id string) (*User, error) {
// реальная реализация
}

// Интерфейс только когда нужен
type UserGetter interface {
GetByID(ctx context.Context, id string) (*User, error)
}


Пакеты должны делать, а не транслировать. Если пакет только переводит между другими пакетами, это шов без назначения. Для большинства сервисов плоская структура cmd/, internal/store/, internal/api/ работает лучше.

Функции вместо интерфейсов, где уместно. Не каждое поведение нужно выражать через интерфейс:
func SendWelcome(ctx context.Context, user User, send func(context.Context, string, string) error) error {
return send(ctx, user.Email, welcomeMessage(user))
}


Называйте по действию, а не по слою. UserActivator, SessionIssuer, PasswordResetter вместо UserService, UserManager, UserHandler. Точность в имени сопротивляется желанию сваливать всё в одну абстракцию.

Простой симптом. Если для одной фичи вы трогаете интерфейс, структуру, конструктор, мок и фикстуру до написания логики, архитектура работает против вас.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoDeep
  • 👍 13
  • 🌚 7
  • 🥱 3
  • 😁 2
  • ❤ 1
Post #7212 3.16K
😌 Дайджест недели

Осталось 7 дней до лета!

— Две уязвимости в golang.org/x/image

В пакете golang.org/x/image исправлены две CVE. Первая вызывала панику при декодировании BMP с некорректным индексом палитры. Вторая позволяла через специально сформированный TIFF-файл заставить декодер потреблять непропорционально много ресурсов при распаковке PackBits.

— Шесть уязвимостей в golang.org/x/net

В пакете golang.org/x/net закрыты шесть CVE. Четыре связаны с XSS через ошибки HTML-парсера, одна позволяет устроить отказ в обслуживании при парсинге HTML, ещё одна открывает возможность обхода проверки доменных имён через некорректную обработку Punycode в пакете idna.

— Vibe теперь и hiring

— Go 1.27 заморожен

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoLive
  • 👾 1
Post #7211 3.09K
📎 sync.Pool в Go, но с дженериками и типобезопасностью

В стандартной библиотеке Go есть sync.Pool. Штука простая по идее, но полезная на практике. Она позволяет переиспользовать объекты вместо того, чтобы каждый раз выделять под них новую память. Меньше аллокаций, меньше нагрузка на GC, выше производительность.

Как это работает

Представьте скоростной принтер, который печатает 100 страниц в минуту. Было бы странно, если бы он перед каждой страницей бегал на склад за новой пачкой бумаги. Вместо этого у него есть лоток на 100 листов. Берём лист, печатаем, кладём обратно. sync.Pool работает по тому же принципу.

Вот как это выглядит в коде:
var paperPool = sync.Pool{
New: func() interface{} {
return new(Paper)
},
}

func printPage() {
page := paperPool.Get().(*Paper)
page.Reset()

defer paperPool.Put(page)

page.Print()
}


Несколько важных моментов про sync.Pool.

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

Ещё один момент. Объекты могут хранить состояние от предыдущего использования. Поэтому перед использованием или перед возвратом в пул их нужно сбрасывать. Если этого не делать, можно получить трудноуловимые баги с «грязными» данными.

Типобезопасная обёртка

sync.Pool хранит и возвращает interface{}. Это гибко, но не безопасно. Ничто не мешает положить в пул строку, а достать и попытаться привести к структуре. Приложение упадёт с паникой.

Дженерики в Go позволяют обернуть sync.Pool так, чтобы тип контролировался на этапе компиляции.
type Pool[T any] struct {
internal sync.Pool
}

func NewPool[T any](newF func() T) *Pool[T] {
return &Pool[T]{
internal: sync.Pool{
New: func() interface{} {
return newF()
},
},
}
}


Мы создали обёртку, привязанную к конкретному типу T. Под капотом всё тот же sync.Pool с interface{}, но снаружи пользователь работает только с типом T.

Теперь методы Get и Put:
func (p *Pool[T]) Get() T {
return p.internal.Get().(T)
}

func (p *Pool[T]) Put(x T) {
p.internal.Put(x)
}


В Get мы приводим interface{} к типу T без проверки ошибки. И это нормально. Наша обёртка гарантирует, что в пул попадают только значения типа T. Функция New создаёт T, метод Put принимает только T. Поэтому приведение типа p.internal.Get().(T) не вызовет панику при штатном использовании.

Код остаётся чистым, типобезопасным и не требует ручных проверок на каждый Get.

Обёртка с дженериками убирает необходимость в ручном приведении типов и снижает риск ошибок. Решение занимает десяток строк, при этом полностью совместимо со стандартным sync.Pool.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoDeep
  • 👍 8
  • ❤ 1
Post #7203 2.82K
📌 Зачем дата-сайентисту матанализ?

Основная компетенция специалиста по Data Science – способность анализировать и интерпретировать данные, а математика является фундаментом для начала работы.

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

Хотите подготовиться к офферу или подтянуть знания? Оставляйте заявку на наш курс по математике для Data Science 💙

P.S. Только до 31 мая на курс (и вообще на все программы Академии) действует СКИДКА 40%

А как у вас дела с высшей математикой?
❤️ — Помню всё
🔥 — Знаю основы
🌚 — Ничего не знаю

🏃‍♀️ Proglib Academy
  • 🔥 5
  • ❤ 3
  • 🌚 3
Post #7202 2.7K
✏️ Мнения разделились

Что выведет:
bytes.ContainsAny([]byte("hello"), "")


Казалось бы, очевидно. Но разработчики разделились почти на четыре группы.

Подсказка: загляните в исходники стандартной библиотеки. Поведение ContainsAny с пустым chars задокументировано — но интуиция здесь часто подводит.

➡️ Правильный ответ в собесах по Go

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#ReadySetGo
  • 🔥 2
Post #7192 2.76K
📊 pprof открывается с Flame Graph по умолчанию

Небольшое изменение в Go 1.26, которое заметно влияет на процесс отладки производительности.

До версии 1.26 команда go tool pprof -http=:8080 открывала top-down tree view. Чтобы переключиться на Flame Graph, нужно было сделать это вручную. На практике многие просто оставались в tree view, потому что оно открывалось первым.

Теперь pprof сразу показывает flame graph. Разница существенная. Flame graph визуально отображает весь стек вызовов: широкие блоки означают медленные функции, высокие столбцы показывают глубокие цепочки вызовов. Tree view содержит ту же информацию, но в виде текстового списка, который требует больше усилий для анализа.

Если в вашей команде регулярно занимаются отладкой производительности, обновите runbook'и и incident playbook'и с учётом нового дефолтного представления.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 👍 8
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →