La specifica del linguaggio Go ( operatori di indirizzo ) non consente di prendere l'indirizzo di una costante numerica (non di una costante non tipizzata né di una costante tipizzata ).
L'operando deve essere indirizzabile , ovvero un'operazione di indirizzamento di una variabile, di un puntatore indiretto o di una sezione; o un selettore di campo di uno struct operando indirizzabile; o un'operazione di indicizzazione di un array di un array indirizzabile. Come eccezione al requisito di indirizzabilità, x
[nell'espressione di &x
] può anche essere un letterale composto (possibilmente tra parentesi) .
Per capire perché ciò non è consentito, vedere la domanda correlata: Trova l'indirizzo della costante in go . Una domanda simile (allo stesso modo non è consentito prendere il suo indirizzo): come posso memorizzare il riferimento al risultato di un'operazione in Go?
Le tue opzioni (prova tutte su Go Playground ):
1) Con new()
Puoi semplicemente usare la new()
funzione incorporata per allocare un nuovo valore zero int64
e ottenere il suo indirizzo:
instance := SomeType{
SomeField: new(int64),
}
Ma si noti che questo può essere utilizzato solo per allocare e ottenere un puntatore al valore zero di qualsiasi tipo.
2) Con variabile helper
Il più semplice e consigliato per elementi diversi da zero è utilizzare una variabile di supporto il cui indirizzo può essere preso:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) Con la funzione di aiuto
Nota: le funzioni di supporto per acquisire un puntatore a un valore diverso da zero sono disponibili nella mia github.com/icza/gox
libreria, ingox
pacchetto, quindi non devi aggiungerle a tutti i tuoi progetti dove ne hai bisogno.
Oppure, se ne hai bisogno molte volte, puoi creare una funzione di supporto che alloca e restituisce un *int64
:
func create(x int64) *int64 {
return &x
}
E usandolo:
instance3 := SomeType{
SomeField: create(3),
}
Nota che in realtà non abbiamo allocato nulla, il compilatore Go lo ha fatto quando abbiamo restituito l'indirizzo dell'argomento della funzione. Il compilatore Go esegue l'analisi di escape e alloca le variabili locali sull'heap (invece che sullo stack) se possono sfuggire alla funzione. Per i dettagli, vedere La restituzione di una porzione di un array locale in una funzione Go è sicura?
4) Con una funzione anonima di una riga
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
O come alternativa (più breve):
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) Con slice literal, indicizzazione e presa indirizzo
Se vuoi *SomeField
essere diverso da0
, allora hai bisogno di qualcosa di indirizzabile.
Puoi ancora farlo, ma è brutto:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
Quello che succede qui è che uno []int64
slice viene creato con un letterale, con un elemento ( 5
). Ed è indicizzato (0 ° elemento) e viene preso l'indirizzo dello 0 ° elemento. Sullo sfondo [1]int64
verrà anche allocato un array di e utilizzato come array di supporto per lo slice. Quindi qui c'è un sacco di boilerplate.
6) Con un helper struct literal
Esaminiamo l'eccezione ai requisiti di indirizzabilità:
Come eccezione al requisito di indirizzabilità, x
[nell'espressione di &x
] può anche essere un letterale composto (possibilmente tra parentesi) .
Ciò significa che prendere l'indirizzo di un letterale composto, ad esempio uno struct literal è ok. Se lo facciamo, avremo il valore della struttura allocato e un puntatore ottenuto ad esso. Ma se è così, un altro requisito diventerà disponibile per noi: "selettore di campo di uno struct operando indirizzabile" . Quindi se la struttura letterale contiene un campo di tipo int64
, possiamo anche prendere l'indirizzo di quel campo!
Vediamo questa opzione in azione. Useremo questo tipo di struttura wrapper:
type intwrapper struct {
x int64
}
E ora possiamo fare:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Nota che questo
&(&intwrapper{6}).x
significa quanto segue:
& ( (&intwrapper{6}).x )
Ma possiamo omettere la parentesi "esterna" quando l'operatore indirizzo &
viene applicato al risultato dell'espressione del selettore .
Si noti inoltre che in background accadrà quanto segue (anche questa è una sintassi valida):
&(*(&intwrapper{6})).x
7) Con helper anonymous struct literal
Il principio è lo stesso del caso # 6, ma possiamo anche usare uno struct letterale anonimo, quindi non è necessaria la definizione del tipo di struttura helper / wrapper:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}