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

Оригинал: 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.

Заключение

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

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

Комментарии (7)


  1. Yak52
    13.10.2025 12:17

    Все таки изучение ассемблера позволяет избежать многих удивлений.


    1. ZSN_2
      13.10.2025 12:17

      Ну если не увидишь, как специалист при переходе с ассемблера на ЯВУ начинает компилировать программу на Си в ассемблерный код для поиска ошибок… ( Си в свое время такое позволял). :)))


    1. doflare123
      13.10.2025 12:17

      И как эти ваши ассемблеры изучать...я смотрю на начало его и уже голова кругом...


  1. ZSN_2
    13.10.2025 12:17

     

                    Худший вариант объяснения, что такое указателей, это начать с ячеек памяти… для людей знакомых только с ЯВУ. В свое время они появились в Си, который позиционировался как «высокоуровневый» ассемблер, вероятно чтобы напрямую работать с памятью и соответственно упростить компиляцию в команды ассемблера. Наворотили специальных обозначений и сделали «головную боль» для бедных программистов.

                    Переменная – это имя и значение (ну и тип в нормальных языках), просто на одно значение может указывать несколько имен и соответственно при операции присваивания нужно различать, что присваивается значение новой переменной или дополнительное имя значению старой переменной.


  1. tentakle
    13.10.2025 12:17

    Из этого текста понятно, что есть указатель (оно и без объяснений понятно), но основная проблема в понимании зачем этот указатель нужен. То же самое можно сделать с помощью переменных и оно будет в разы понятнее, без всяких этих разыменований.


  1. AskePit
    13.10.2025 12:17

    Интересно, при чем здесь конкретно Go - понятие указателя существовало за много десятилетий до этого языка


    1. georgri
      13.10.2025 12:17

      Вот да, я ожидал что-то про Garbage collector в golang и как он работает с указателями.