
Об указателях в C/C++ рассказывают страшные истории. Однако указатели в Go очень просты и удобны: два использования оператора звездочки, одно использование оператора амперсанда, и все готово.
Давайте посмотрим на них в истории жизни переменных a, b, c и d.
a := 42
2. b также хотел бы поделиться драгоценной ценностью с a
b := a
3. Затем есть c, который хочет хранить не целочисленное значение, а адрес целочисленной переменной
Первое использование оператора звездочки: когда он ставится перед типом, он означает, что указатель указывает только на переменные этого конкретного типа.
var c *int
Использование оператора амперсанда:если он ставится перед переменной, он возвращает адрес этой переменной.
c = &a
4. Теперь у нас есть черный ход для доступа к a
Второе использование оператора звездочки: когда он помещается перед указателем, он возвращает переменную, находящуюся в адресе, который представляет указатель.
*c // This basically gives us the variable a
5. Изменение значения b не влияет на a , поскольку единственная связь b с a заключается в том, что он просто скопировал его значение один раз.
b = 43 // variable a still has the value 42
6. Однако, поскольку c знает, где aживет, с c мы можем делать все, что захотим a
*c = 44 // now variable a's value is set to 44, no longer the answer to the ultimate question...
7. Более того, пусть переменная d скопирует значение c, чтобы у нас было две переменные *int, которые знают, где живет a
d := c
8. Теперь с *d у нас также есть полный контроль над (бедными) a
*d = 45 // now both a and *c give back 45
Указатели Go сами по себе являются переменными. Два указателя, указывающих на один и тот же адрес (например, c и d ), по-прежнему полностью независимы, каждый занимает свой собственный адрес в памяти. Самая запутанная ситуация C++, когда одна и та же память представлена несколькими псевдонимами или ссылками на переменные, в Go не произойдет.
Другая заманчивая идея заключается в том, могут ли указатели на разные типы присваиваться друг другу, поскольку все они хранят адреса памяти. Ответ «нет», даже для базовых типов:
type i int var a i a = 1 var b *int b = &a // You can't do this!