Prefacio: Sin discutir que ese if else
es el camino a seguir, aún podemos jugar y encontrar placer en las construcciones habilitadas por el lenguaje.
La siguiente If
construcción está disponible en mi github.com/icza/gox
biblioteca con muchos otros métodos, siendo el builtinx.If
tipo.
Go permite adjuntar métodos a cualquier tipo definido por el usuario , incluidos los tipos primitivos como bool
. Podemos crear un tipo personalizado teniendo bool
como 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 a
y 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 .