Предисловие: не споря, что if else
это путь, мы все еще можем играть и получать удовольствие от конструкций с поддержкой языка.
Следующая If
конструкция доступна в моей github.com/icza/gox
библиотеке с множеством других методов, являющихся builtinx.If
типом.
Go позволяет прикреплять методы к любым пользовательским типам , включая такие примитивные, как bool
. Мы можем создать пользовательский тип , имеющий в bool
качестве базового типа , а затем с помощью простого типа преобразования при условии, мы имеем доступ к его методам. Методы, которые получают и выбирают из операндов.
Что-то вроде этого:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
Как мы можем использовать это?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Например троичный делает max()
:
i := If(a > b).Int(a, b)
Троицы делают abs()
:
i := If(a >= 0).Int(a, -a)
Это выглядит круто, это просто, изящно, и эффективно (это также имеет право на встраивание ).
Один недостаток по сравнению с «настоящим» троичным оператором: он всегда оценивает все операнды.
Для достижения отложенной и только в случае необходимости оценки, единственный вариант - использовать функции (либо объявленные функции или методы, либо литералы функций ), которые вызываются только когда / при необходимости:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Используя его: давайте предположим, что у нас есть эти функции для вычисления a
и b
:
func calca() int { return 3 }
func calcb() int { return 4 }
Затем:
i := If(someCondition).Fint(calca, calcb)
Например, текущее состояние> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Если мы хотим использовать функциональные литералы:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Последнее замечание: если у вас будут функции с разными сигнатурами, вы не сможете использовать их здесь. В этом случае вы можете использовать функциональный литерал с соответствующей сигнатурой, чтобы сделать их все еще применимыми.
Например, если calca()
и calcb()
будет иметь параметры (кроме возвращаемого значения):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
Вот как вы можете их использовать:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Попробуйте эти примеры на игровой площадке Go .