golang

Поймите указатели в Go меньше чем за 800 слов или вернём деньги

  • вторник, 14 октября 2025 г. в 00:00:11
https://habr.com/ru/articles/956040/

Не нашел перевод этой статьи, решил сделать, ногами не бейте

Оригинал: Understand Go pointers in less than 800 words or your money back
Автор: Дэйв Чейни
Дата: 26 апреля 2017 г.

Проще говоря, указатель — это значение, которое указывает на адрес другого значения. Это определение из учебников, но если вы пришли из языка, который не позволяет работать с адресами переменных, эта фраза может показаться магической.

Давайте разберемся.

Что такое память?

Компьютерная память (RAM) — это последовательность ячеек, расположенных друг за другом. Каждая ячейка обозначена уникальным числом (адресом), который увеличивается последовательно: это и есть адрес этой ячейки.

Каждая ячейка хранит одно значение. Если вы знаете адрес ячейки, вы можете считать из нее содержимое или записать туда новое. Всё, что делает процессор, — это извлекает и помещает значения в эти ячейки памяти.

Что такое переменная?

Допустим, нам нужно написать программу, которая берет значение из ячейки с адресом 200, умножает его на 3 и помещает результат в ячейку 201. Это можно записать на псевдокоде так:

  • получить значение по адресу 200 и поместить его в процессор

  • умножить его на 3

  • записать результат в адрес 201

Ранние программы так и писались: программист вел список адресов используемой памяти, кто и когда их использует, что там хранится. Но это было утомительно и чревато ошибками: все значения должны были иметь свой уникальный адрес, и нельзя было динамически выделять память под переменные во время выполнения.

Для решения этой проблемы появилось понятие переменной. Переменная — это просто удобный буквенно-цифровой псевдоним для адреса в памяти; метка или никнейм.

Теперь вместо работы напрямую с адресами, мы можем использовать имена переменных. Приведённый выше код можно теперь записать как:

• получить значение переменной a и поместить в процессор

• умножить на 3

• записать в переменную b

Это та же самая программа, но гораздо удобнее: нам больше не нужно следить за адресами — этим займется компилятор.

Теперь мы можем написать:

var a = 6
var b = a * 3

И компилятор выделит уникальные адреса под a и b автоматически.

Что такое указатель?

Теперь, когда мы знаем, что память — это просто последовательные ячейки, а переменные — имена этих ячеек, возникает вопрос: что такое указатель?

Указатель — это значение, которое хранит адрес другой переменной.

Указатель указывает на адрес переменной, так же как переменная отвечает за адрес, по которому хранится её значение.

Посмотрим на пример:

func main() {
    a := 200
    b := &a
    *b++
    fmt.Println(a)
}

В первой строке функции main мы объявляем переменную a и присваиваем ей значение 200.

Далее объявляется переменная b и ей присваивается адрес a. Мы не знаем, где в памяти хранится a, но можем сохранить её адрес в b.

Третья строка, вероятно, самая запутанная. b содержит адрес переменной a, но мы хотим увеличить значение, хранящееся в a. Для этого нужно разыменовать b, то есть пройти по адресу из b и получить содержимое из a.

Затем мы увеличиваем это значение на 1 и снова записываем по адресу, хранящемуся в b.

Последняя строка выводит значение a — оно стало 201.

Заключение

Если вы пришли из языка без явных указателей или где каждая переменная по сути является указателем — не переживайте. На формирование ментальной модели переменных и указателей уходит время и практика — просто запомните:

Указатель — это значение, которое указывает на адрес другой переменной.