Prefacio: Sin discutir que ese if elsees el camino a seguir, aún podemos jugar y encontrar placer en las construcciones habilitadas por el lenguaje.
La siguiente Ifconstrucción está disponible en mi github.com/icza/goxbiblioteca con muchos otros métodos, siendo el builtinx.Iftipo.
Go permite adjuntar métodos a cualquier tipo definido por el usuario , incluidos los tipos primitivos como bool. Podemos crear un tipo personalizado teniendo boolcomo tipo subyacente , y luego con una conversión de tipo simple en la condición, tenemos acceso a sus métodos. Métodos que reciben y seleccionan de los operandos.
Algo como esto:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
¿Cómo podemos usarlo?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Por ejemplo, un ternario que hace max():
i := If(a > b).Int(a, b)
Un ternario haciendo abs():
i := If(a >= 0).Int(a, -a)
Esto se ve genial, es simple, elegante y eficiente (también es elegible para la inserción ).
Una desventaja en comparación con un operador ternario "real": siempre evalúa todos los operandos.
Para lograr una evaluación diferida y solo si es necesaria, la única opción es usar funciones (ya sea funciones o métodos declarados , o literales de función ), que solo se llaman cuando / si es necesario:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Uso: supongamos que tenemos estas funciones para calcular ay b:
func calca() int { return 3 }
func calcb() int { return 4 }
Luego:
i := If(someCondition).Fint(calca, calcb)
Por ejemplo, la condición es el año actual> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Si queremos usar literales de función:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Nota final: si tuviera funciones con diferentes firmas, no podría usarlas aquí. En ese caso, puede usar una función literal con la firma correspondiente para que sigan siendo aplicables.
Por ejemplo, si calca()y calcb()también tuviera parámetros (además del valor de retorno):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
Así es como puedes usarlos:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Pruebe estos ejemplos en Go Playground .