Avant-propos: Sans prétendre que if else
c'est la voie à suivre, nous pouvons toujours jouer avec et trouver du plaisir dans les constructions basées sur le langage.
La If
construction suivante est disponible dans ma github.com/icza/gox
bibliothèque avec beaucoup d'autres méthodes, étant le builtinx.If
type.
Go permet d'attacher des méthodes à tous les types définis par l'utilisateur , y compris les types primitifs tels que bool
. Nous pouvons créer un type personnalisé ayant bool
comme type sous-jacent , puis avec une conversion de type simple à la condition, nous avons accès à ses méthodes. Méthodes qui reçoivent et sélectionnent les opérandes.
Quelque chose comme ça:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
Comment pouvons-nous l'utiliser?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Par exemple un ternaire faisant max()
:
i := If(a > b).Int(a, b)
Un ternaire faisant abs()
:
i := If(a >= 0).Int(a, -a)
Cela a l'air cool, c'est simple, élégant et efficace (il est également éligible pour l'inline ).
Un inconvénient par rapport à un "vrai" opérateur ternaire: il évalue toujours tous les opérandes.
Pour obtenir une évaluation différée et uniquement si nécessaire, la seule option consiste à utiliser des fonctions (soit des fonctions ou méthodes déclarées , soit des littéraux de fonction ), qui ne sont appelées que lorsque / si nécessaire:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Utilisation: Supposons que nous avons ces fonctions pour calculer a
et b
:
func calca() int { return 3 }
func calcb() int { return 4 }
Ensuite:
i := If(someCondition).Fint(calca, calcb)
Par exemple, la condition étant l'année en cours> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Si nous voulons utiliser des littéraux de fonction:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Remarque finale: si vous aviez des fonctions avec des signatures différentes, vous ne pourriez pas les utiliser ici. Dans ce cas, vous pouvez utiliser un littéral de fonction avec une signature correspondante pour les rendre toujours applicables.
Par exemple, si calca()
et calcb()
aurait également des paramètres (en plus de la valeur de retour):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
Voici comment vous pouvez les utiliser:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Essayez ces exemples sur le Go Playground .