Premessa: Senza discutere che if else
sia la strada da percorrere, possiamo ancora giocare e trovare piacere nei costrutti abilitati al linguaggio.
Il seguente If
costrutto è disponibile nella mia github.com/icza/gox
libreria con molti altri metodi, essendo il builtinx.If
tipo.
Go consente di associare metodi a qualsiasi tipo definito dall'utente , inclusi tipi primitivi come bool
. Possiamo creare un tipo personalizzato avente bool
come tipo sottostante , e quindi con una semplice conversione del tipo a condizione, abbiamo accesso ai suoi metodi. Metodi che ricevono e selezionano dagli operandi.
Qualcosa come questo:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
Come possiamo usarlo?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Ad esempio un ternario che fa max()
:
i := If(a > b).Int(a, b)
Un ternario che fa abs()
:
i := If(a >= 0).Int(a, -a)
Sembra bello, semplice, elegante ed efficiente (è idoneo anche per l'allineamento ).
Un aspetto negativo rispetto a un "vero" operatore ternario: valuta sempre tutti gli operandi.
Per ottenere una valutazione differita e solo se necessaria, l'unica opzione è utilizzare le funzioni ( funzioni o metodi dichiarati o valori letterali delle funzioni ), che vengono chiamate solo quando / se necessario:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Usandolo: supponiamo di avere queste funzioni per calcolare a
e b
:
func calca() int { return 3 }
func calcb() int { return 4 }
Poi:
i := If(someCondition).Fint(calca, calcb)
Ad esempio, la condizione è l'anno corrente> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Se vogliamo usare i letterali delle funzioni:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Nota finale: se avessi funzioni con firme diverse, non potresti usarle qui. In tal caso è possibile utilizzare una funzione letterale con firma corrispondente per renderli ancora applicabili.
Ad esempio se calca()
e calcb()
avrebbe anche dei parametri (oltre al valore restituito):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
Ecco come potresti usarli:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Prova questi esempi sul Go Playground .