Границы указателей †
Во время аудита Миша наткнулся на старую часть проекта: связку с C-библиотекой разбора форматов. «Работает — не трогаем, — решил Сергей. — Здесь язык не защищает, здесь граница».
в Go нет арифметики указателей — это осознанное ограничение ради безопасности и совместимости со сборщиком мусора; редкие места, где она нужна, покрывает unsafe.
В Go нет арифметики указателей. Нельзя написать p + 1, чтобы пройти к следующему элементу, нельзя перескакивать по памяти произвольными шагами, нельзя кастить указатель на структуру в указатель на число.
Что не скомпилируется
p := &size
p + 1 // ошибка компиляции
*p + 1 // а вот это работает: прибавили к значению, а не к адресу
Разница между p + 1 и *p + 1 — ровно та же, что между &x и *p из прошлого урока: первое — про адрес, второе — про значение. Адресную арифметику язык не даёт.
Почему ограничение и где его обходят
Это осознанное решение: арифметика указателей — источник целого класса багов, от переполнения буфера до несовместимости со сборщиком мусора, которому нужно точно знать, где в памяти лежат указатели.
Для тех редких мест, где арифметика реально нужна — связь с C через cgo, некоторые системные вызовы — есть unsafe.Pointer и uintptr. Именно так устроена старая часть «Полки», работающая с C-библиотекой. Но они на то и unsafe: компилятор и рантайм снимают с себя гарантии безопасности, как только ты туда лезешь. Имя пакета — предупреждение, а не название.
Вы узнаете:
- как Go-код через cgo вызывает C и почему там
unsafe.Pointer - как GC размечает указатели и почему произвольные адреса ему мешают
Проверьте себя
p := &size. Что произойдёт при p + 1?
Зачем сборщику мусора точно знать, где в памяти лежат указатели?
Какие гарантии снимает с себя unsafe при использовании unsafe.Pointer и uintptr?
правильных ответов
Указатели в Go — «безопасные»: ни арифметики, ни произвольных приведений. Нужно что-то низкоуровневое — unsafe, но с пониманием, что гарантии языка отключаются.
10 000 ₽ · 60 минут · онлайн