MXStat
MXStat
Введите текст для поиска
Расширенный поиск каналов
  • Вход на сайт
  • Каталог
    Каталог каналов Региональные подборки Поиск каналов
    Добавить канал
  • Рейтинги
    Рейтинг каналов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Max
Библиотека Go (Golang) разработчика

2 Sep, 10:27

Открыть в Max Поделиться

☢️ Пакет 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

363 2
Каталог
Каталог каналов Подборки каналов Поиск каналов Добавить канал
Рейтинги
Рейтинг каналов Max
Контакты
Написать в Max Написать в Telegram Написать на почту
Всякая всячина
Пользовательское соглашение Политика конфиденциальности
Наши каналы
MXStat в Telegram MXStat в Max
Наши боты
MXAuthBot MXAnalyticsBot
Made by TGStat