&Person{}
является языковой «конструкцией», она является частью спецификации: она выделяет новую переменную типа Person
и предоставляет вам адрес этой анонимной переменной.
Spec: Составные литералы:
При получении адреса составного литерала создается указатель на уникальную переменную , инициализированную значением литерала.
Также: Спецификация: Переменные:
Вызов встроенной функции new или с использованием адреса составного литерала выделяет память для переменной во время выполнения .
&999
не допускается языковой спецификацией. Возможные операнды операторов адреса перечислены в Spec: Операторы адреса:
Операнд должен быть адресуемым , то есть либо переменной, либо косвенным указателем, либо операцией индексации слайса; или селектор поля адресуемого структурного операнда; или операция индексации массива адресуемого массива. В качестве исключения из требования адресуемости, x
также может быть (возможно заключенным в скобки) составным литералом .
p := Person{}
создает новую переменную p
, тип которой будет Person
. p := &Person{}
создает новую переменную, тип которой будет *Person
.
Просмотр возможного дубликата: Как мне сделать литерал * int64 в Go?
Когда вы печатаете значения с пакетом fmt
, у него есть определенные правила для печати значений разных типов:
Для составных объектов элементы печатаются с использованием этих правил, рекурсивно, расположенных следующим образом:
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2]
pointer to above: &{}, &[], &map[]
Когда вы используете fmt.Println()
, будут применяться правила форматирования по умолчанию, которые для значения типа *int
являются глаголом %p
, который будет печатать адрес памяти в шестнадцатеричном формате, но для указателя на структуру он печатает значение структуры с добавлением знака &
(&{}
). Вы можете прочитать больше об этом в связанном вопросе: Разница между указателями Голанга
Если вы хотите напечатать указанное значение, разыменуйте указатель и передайте указанное значение, например ::
.
var p = new(int)
*p = 12
fmt.Println(*p) // Prints 12
Относительно того, почему нужно создать указатель на значение (а не значение), см. Следующие связанные вопросы:
Указатели против значений в параметрах и возвращаемых значениях
Зачем конструктору обратный адрес Go?
Go, X не реализует Y (... у метода есть указатель на приемник)