Ответ 1
Спецификация языка Go (Операторы адресов) не позволяет принимать адрес числовой константы (а не нетипированной или типичной константа).
Операнд должен быть адресуемым, то есть либо переменной, либо указателем, либо индексированием фрагмента; или селектор поля адресного структурного операнда; или операцию индексирования массива адресного массива. В качестве исключения для требования адресности
x
[в выражении&x
] также может быть (возможно, в скобках) составным литералом.
Для объяснения причин, почему это не разрешено, см. соответствующий вопрос: Найти адрес константы в go. Аналогичный вопрос (аналогично не позволяющий принять его адрес): Как сохранить ссылку на результат операции в Go?
Ваши параметры (попробуйте все на Go Playground):
1) С new()
Вы можете просто использовать встроенную функцию new()
для выделения нового нулевого знака int64
и получить его адрес:
instance := SomeType{
SomeField: new(int64),
}
Но учтите, что это можно использовать только для выделения и получения указателя на нулевое значение любого типа.
2) С лителом среза, индексированием и принятием адреса
Если вы хотите, чтобы *SomeField
был отличным от 0
, вам нужно что-то адресное.
Вы все еще можете это сделать, но это уродливо:
instance2 := SomeType{
SomeField: &[]int64{2}[0],
}
fmt.Println(*instance2.SomeField) // Prints 2
Здесь происходит фрагмент []int64
, созданный с помощью литерала, имеющего один элемент (2
). И он индексируется (0-й элемент) и берется адрес 0-го элемента. В фоновом режиме массив [1]int64
также будет выделен и использован в качестве массива поддержки для среза. Так что здесь много шаблонов.
3) С помощью вспомогательной переменной
Простейшим и рекомендуемым для ненулевых элементов является использование вспомогательной переменной, адрес которой можно взять:
helper := int64(3)
instance3 := SomeType{
SomeField: &helper,
}
4) С помощью вспомогательной функции
Или, если вам это нужно много раз, вы можете создать вспомогательную функцию, которая выделяет и возвращает *int64
:
func create(x int64) *int64 {
return &x
}
И используя его:
instance4 := SomeType{
SomeField: create(4),
}
5) с однострочной анонимной функцией
instance5 := SomeType{
SomeField: func() *int64 { i := int64(5); return &i }(),
}
Или как (более короткая) альтернатива:
instance5 := SomeType{
SomeField: func(i int64) *int64 { return &i }(5),
}
6) Со вспомогательным строковым литералом
Давайте рассмотрим исключение для требований адресности:
В качестве исключения для требования адресности
x
[в выражении&x
] также может быть (возможно, в скобках) составной литерал.
Это означает, что, принимая адрес составного литерала, например, строковый литерал в порядке. Если мы это сделаем, у нас будет выделено значение структуры и получен указатель. Но если это так, нам будет доступно другое требование: селектор полей "адресного операнда структуры" . Поэтому, если строковый литерал содержит поле типа int64
, мы также можем взять адрес этого поля!
Посмотрите эту опцию в действии. Мы будем использовать этот тип структуры оболочки:
type intwrapper struct {
x int64
}
И теперь мы можем сделать:
i6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Обратите внимание, что это
&(&intwrapper{6}).x
означает следующее:
& ( (&intwrapper{6}).x )
Но мы можем опустить "внешнюю" скобку, поскольку адресный оператор &
применяется к результату выражения .
Также обратите внимание, что в фоновом режиме произойдет следующее (это также действительный синтаксис):
&(*(&intwrapper{6})).x
7) Со вспомогательным анонимным строковым литералом
Принцип тот же, что и в случае С# 6, но мы также можем использовать анонимный строковый литерал, поэтому не требуется определение типа структуры помощника/оболочки:
i7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}