Prefácio: Sem argumentando queif else
é o caminho a seguir, ainda podemos brincar e encontrar prazer em construções habilitadas para idiomas.
A If
construção a seguir está disponível na minha github.com/icza/gox
biblioteca com muitos outros métodos, sendo o builtinx.If
tipo
Go permite anexar métodos a qualquer tipo definido pelo usuário , incluindo tipos primitivos como bool
. Podemos criar um tipo personalizado tendo bool
como tipo subjacente e, em seguida, com uma simples conversão de tipo na condição, teremos acesso a seus métodos. Métodos que recebem e selecionam dos operandos.
Algo assim:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
Como podemos usá-lo?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Por exemplo, um ato ternário max()
:
i := If(a > b).Int(a, b)
Um ato ternário abs()
:
i := If(a >= 0).Int(a, -a)
Parece legal, é simples, elegante e eficiente (também é elegível para inlining ).
Uma desvantagem em comparação com um operador ternário "real": ele sempre avalia todos os operandos.
Para obter uma avaliação adiada e apenas se necessário, a única opção é usar funções ( funções ou métodos declarados ou literais de função ), que são chamados apenas quando / se necessário:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Usando-o: Vamos assumir que temos essas funções para calcular a
e b
:
func calca() int { return 3 }
func calcb() int { return 4 }
Então:
i := If(someCondition).Fint(calca, calcb)
Por exemplo, a condição sendo o ano atual> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Se queremos usar literais de função:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Nota final: se você tiver funções com diferentes assinaturas, não poderá usá-las aqui. Nesse caso, você pode usar uma função literal com assinatura correspondente para torná-las ainda aplicáveis.
Por exemplo, se calca()
e calcb()
também teria parâmetros (além do valor de retorno):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
É assim que você pode usá-los:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Experimente estes exemplos no Go Playground .