Пост канала
☢️ Пакет unsafe: Взламываем систему типов Go Пакет unsafe - это легальный способ сказать компилятору: «Отключи ремни безопасности, я беру управление на себя». С его помощью можно обходить строгую типизацию и напрямую управлять памятью, но любая ошибка приведет к моментальному падению сервиса (Segmentation Fault). Проблема стандартной конвертации В Go строки (string) иммутабельны (неизменяемы), а срезы байт ([]byte) можно менять. Когда вы пишете s := string(bytes), Go вынужден копировать всю память. Это делается для того, чтобы вы не смогли изменить исходный массив и случайно поменять символы в строке. В высоконагруженных местах (парсинг JSON, HTTP-роутеры) эти копирования плодят мусор и съедают CPU. Zero-allocation конвертация (Go 1.20+) Долгое время разработчики занимались черной магией, жонглируя внутренними структурами StringHeader и SliceHeader через указатели. С версии Go 1.20 в язык добавили элегантные функции unsafe.String и unsafe.Slice. import "unsafe" // Из []byte в string без копирования памяти func BytesToString(b []byte) string { if len(b) == 0 { return "" } // Говорим Go: "Смотри на этот кусок памяти как на строку" return unsafe.String(&b[0], len(b)) } // Из string в []byte без аллокаций func StringToBytes(s string) []byte { if len(s) == 0 { return nil } return unsafe.Slice(unsafe.StringData(s), len(s)) } В чем смертельная опасность? Вы обманули компилятор, но физика осталась прежней. Если вы превратили string в []byte с помощью unsafe, а затем попытались изменить этот срез (например, b[0] = 'X'), ваша программа мгновенно упадет. Строки часто хранятся в защищенной от записи секции памяти (read-only). Попытка записи туда вызывает панику на уровне операционной системы, которую невозможно перехватить через recover(). Когда это реально нужно? • Написание сверхбыстрых логгеров (популярные библиотеки вроде zap или zerolog используют это под капотом). • Парсинг потоковых сетевых протоколов, где вы просто читаете миллионы пакетов без их модификации. • Только тогда, когда pprof явно показал, что функция runtime.slicebytetostring является главным узким местом приложения. GC и устаревший API Если вы поддерживаете легаси-код на старых версиях Go, где используется reflect.StringHeader с полем Data uintptr - срочно переписывайте. Garbage Collector в Go не видит связи между uintptr и реальным объектом в памяти. При неудачном тайминге GC мог очистить память, пока вы с ней работали. Новые методы unsafe.String сохраняют ссылочную целостность для сборщика мусора. #golang #unsafe #performance #underhood #hardcore 👉 @golang_lib
Открыть в MAX- Просмотры
- 379
- ER
- 0,5%
- Реакции
- 2