Существует ли в Go адресная арифметика?

Ответ

В 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).