Ответ
В Go, в его безопасной части, нет адресной арифметики, в отличие от C/C++. Указатели в Go спроектированы быть безопасными: они могут быть nil
или указывать на действительный объект в памяти, но с ними нельзя производить арифметические операции (например, ptr++
).
Однако для низкоуровневых операций, где требуется прямой доступ к памяти, существует пакет unsafe
.
Пакет unsafe
Он позволяет обойти систему типов Go. С его помощью можно преобразовать указатель в тип uintptr
(целочисленный тип, достаточный для хранения адреса), выполнить над ним арифметические операции, а затем преобразовать обратно в unsafe.Pointer
.
Пример:
package main
import (
"fmt"
"unsafe"
)
func main() {
arr := [3]int{10, 20, 30}
// Получаем указатель на первый элемент
p := &arr[0]
// Преобразуем в unsafe.Pointer, затем в uintptr для арифметики
// uintptr - это просто число, а не указатель
addr := uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(arr[0])
// Преобразуем адрес обратно в типизированный указатель
nextP := (*int)(unsafe.Pointer(addr))
fmt.Println(*nextP) // Выведет: 20
}
Важно: Использование unsafe
ломает гарантии безопасности типов и памяти в Go и может привести к непредсказуемому поведению или панике. Его следует применять только в исключительных случаях, например:
- Для критической оптимизации производительности.
- При взаимодействии с кодом на C через
Cgo
. - При реализации очень низкоуровневых структур данных.
В подавляющем большинстве случаев следует использовать безопасные альтернативы, такие как срезы (slices).