The Go Specification Language ( operadores de endereço faz) não permite tomar o endereço de uma constante numérica (não de um sem tipo nem de um digitado constante).
O operando deve ser endereçável , ou seja, uma variável, indireção de ponteiro ou operação de indexação de fatia; ou um seletor de campo de um operando de estrutura endereçável; ou uma operação de indexação de matriz de uma matriz endereçável. Como uma exceção ao requisito de endereçabilidade, x
[na expressão de &x
] também pode ser um literal composto (possivelmente entre parênteses) .
Para saber por que isso não é permitido, consulte a pergunta relacionada: Encontre o endereço da constante em go . Uma pergunta semelhante (da mesma forma não tem permissão para levar seu endereço): Como posso armazenar a referência ao resultado de uma operação em Go?
Suas opções (experimente tudo no Go Playground ):
1) Com new()
Você pode simplesmente usar a new()
função integrada para alocar um novo valor zero int64
e obter seu endereço:
instance := SomeType{
SomeField: new(int64),
}
Mas observe que isso só pode ser usado para alocar e obter um ponteiro para o valor zero de qualquer tipo.
2) Com variável auxiliar
O mais simples e recomendado para elementos diferentes de zero é usar uma variável auxiliar cujo endereço pode ser obtido:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) Com função auxiliar
Nota: As funções auxiliares para adquirir um ponteiro para um valor diferente de zero estão disponíveis em minha github.com/icza/gox
biblioteca, no gox
pacote, portanto, você não precisa adicioná-las a todos os seus projetos onde precisar.
Ou, se você precisar disso muitas vezes, pode criar uma função auxiliar que aloca e retorna um *int64
:
func create(x int64) *int64 {
return &x
}
E usando:
instance3 := SomeType{
SomeField: create(3),
}
Observe que, na verdade, não alocamos nada, o compilador Go fez isso quando retornamos o endereço do argumento da função. O compilador Go executa a análise de escape e aloca variáveis locais no heap (em vez da pilha) se elas podem escapar da função. Para obter detalhes, consulte O retorno de uma fatia de um array local em uma função Go é seguro?
4) Com uma função anônima de uma linha
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
Ou como uma alternativa (mais curta):
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) Com literal de fatia, indexação e obtenção de endereço
Se você quiser *SomeField
ser diferente de 0
, então precisa de algo endereçável.
Você ainda pode fazer isso, mas é feio:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
O que acontece aqui é que uma []int64
fatia é criada com um literal, tendo um elemento ( 5
). E é indexado (0º elemento) e o endereço do 0º elemento é obtido. No fundo, uma matriz de [1]int64
também será alocada e usada como matriz de apoio para a fatia. Portanto, há muito clichê aqui.
6) Com um literal de estrutura auxiliar
Vamos examinar a exceção aos requisitos de endereçamento:
Como uma exceção ao requisito de endereçamento, x
[na expressão de &x
] também pode ser um literal composto (possivelmente entre parênteses) .
Isso significa que pegar o endereço de um literal composto, por exemplo, um literal de estrutura está ok. Se fizermos isso, teremos o valor da estrutura alocado e um ponteiro obtido para ele. Mas se for assim, outro requisito se tornará disponível para nós: "seletor de campo de um operando de estrutura endereçável" . Portanto, se o literal de estrutura contém um campo do tipo int64
, também podemos obter o endereço desse campo!
Vamos ver essa opção em ação. Usaremos este tipo de estrutura de wrapper:
type intwrapper struct {
x int64
}
E agora podemos fazer:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Observe que este
&(&intwrapper{6}).x
significa o seguinte:
& ( (&intwrapper{6}).x )
Mas podemos omitir o parêntese "externo", pois o operador de endereço &
é aplicado ao resultado da expressão do seletor .
Observe também que em segundo plano acontecerá o seguinte (esta também é uma sintaxe válida):
&(*(&intwrapper{6})).x
7) Com literal de estrutura anônima auxiliar
O princípio é o mesmo do caso nº 6, mas também podemos usar um literal de estrutura anônima, portanto, nenhuma definição de tipo de estrutura auxiliar / wrapper é necessária:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}