Специфікація мови Go ( оператори адрес ) не дозволяє приймати адресу числової константи (а не нетипізованої та не введеної константи).
Операнд повинен бути адресним , тобто або змінною, непрямим вказівником або операцією індексування зрізу; або селектор поля адресного структурного операнда; або операція індексації масиву адресного масиву. Як виняток із вимоги адресації, x
[у виразі &x
] також може бути (можливо, у дужках) складений літерал .
Для аргументації, чому це не дозволено, див. Відповідне запитання: Знайдіть адресу константи в go . Подібне запитання (так само заборонено приймати його адресу): Як я можу зберегти посилання на результат операції в Go?
Ваші варіанти (спробуйте все на майданчику Go ):
1) З new()
Ви можете просто використовувати вбудовану new()
функцію, щоб виділити нове нульове значення int64
та отримати його адресу:
instance := SomeType{
SomeField: new(int64),
}
Але зауважте, що це можна використовувати лише для виділення та отримання вказівника на нульове значення будь-якого типу.
2) З допоміжною змінною
Найпростішим і рекомендованим для ненульових елементів є використання допоміжної змінної, адресу якої можна взяти:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) З допоміжною функцією
Примітка: Допоміжні функції для отримання вказівника на ненульове значення доступні в моїй github.com/icza/gox
бібліотеці, в gox
пакеті, тому вам не потрібно додавати їх у всі свої проекти, де вам це потрібно.
Або якщо вам потрібно це багато разів, ви можете створити допоміжну функцію, яка виділяє та повертає *int64
:
func create(x int64) *int64 {
return &x
}
І використовуючи його:
instance3 := SomeType{
SomeField: create(3),
}
Зауважте, що насправді ми нічого не виділяли, компілятор Go це зробив, коли ми повернули адресу аргументу функції. Компілятор Go виконує аналіз екранування та виділяє локальні змінні в купі (замість стека), якщо вони можуть уникнути функції. Детальніше див. У розділі Чи повернення фрагмента локального масиву у функції Go безпечно?
4) З анонімною функцією з одним вкладишем
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
Або як (коротшу) альтернативу:
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) З буквальним фрагментом, індексацією та адресою збору
Якщо ви хочете *SomeField
бути іншим, ніж 0
, тоді вам потрібно щось адресоване.
Ви все ще можете це зробити, але це негарно:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
Тут відбувається те, що []int64
фрагмент створюється з літералом, що має один елемент ( 5
). І він індексується (0-й елемент) і береться адреса 0-го елемента. У фоновому режимі [1]int64
також буде виділено масив з, який буде використовуватися в якості резервного масиву для зрізу. Отже, тут багато шаблону.
6) З допоміжним структурним літералом
Давайте розглянемо виняток із вимог адресації:
Як виняток із вимоги адресації, x
[у виразі &x
] також може бути (можливо, у дужках) складений літерал .
Це означає, що прийняття адреси складеного літералу, наприклад, структурного літералу - це нормально. Якщо ми зробимо це, нам буде призначено значення struct і отриманий на нього покажчик. Але якщо це так, нам стане доступна ще одна вимога: "селектор поля адресного структурного операнда" . Отже, якщо літерал struct містить поле типу int64
, ми також можемо взяти адресу цього поля!
Давайте розглянемо цей варіант у дії. Ми будемо використовувати цей тип структури обгортки:
type intwrapper struct {
x int64
}
І тепер ми можемо зробити:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Зауважте, що це
&(&intwrapper{6}).x
означає наступне:
& ( (&intwrapper{6}).x )
Але ми можемо опустити "зовнішню" дужку, оскільки оператор адреси &
застосовується до результату виразу селектора .
Також зауважте, що у фоновому режимі відбуватиметься наступне (це також допустимий синтаксис):
&(*(&intwrapper{6})).x
7) З допоміжним анонімним структурним літералом
Принцип такий самий, як і у випадку №6, але ми також можемо використовувати анонімний структурний літерал, тому не потрібне визначення типу структури помічника / обгортки:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}