Przedmowa: Bez kłócenia się, że if else
tak należy, nadal możemy bawić się i czerpać przyjemność z konstrukcji opartych na języku.
Poniższy If
konstrukt jest dostępny w mojej github.com/icza/gox
bibliotece z wieloma innymi metodami, które są builtinx.If
typem.
Go pozwala na dołączanie metod do dowolnych typów zdefiniowanych przez użytkownika , w tym typów pierwotnych, takich jak bool
. Możemy stworzyć typ niestandardowy mający bool
jako jego typ podstawowy , a następnie przy pomocy prostej konwersji typu pod warunkiem mamy dostęp do jego metod. Metody, które odbierają i wybierają spośród argumentów.
Coś takiego:
type If bool
func (c If) Int(a, b int) int {
if c {
return a
}
return b
}
Jak możemy tego użyć?
i := If(condition).Int(val1, val2) // Short variable declaration, i is of type int
|-----------| \
type conversion \---method call
Na przykład trójka robi max()
:
i := If(a > b).Int(a, b)
Trójka robi abs()
:
i := If(a >= 0).Int(a, -a)
Wygląda to fajnie, jest proste, eleganckie i wydajne (nadaje się również do wstawiania ).
Jeden minus w porównaniu do „prawdziwego” operatora trójskładnikowego: zawsze ocenia wszystkie operandy.
Aby uzyskać odroczoną i tylko w razie potrzeby ocenę, jedyną opcją jest użycie funkcji ( deklarowanych funkcji lub metod lub literałów funkcji ), które są wywoływane tylko wtedy, gdy jest to konieczne:
func (c If) Fint(fa, fb func() int) int {
if c {
return fa()
}
return fb()
}
Korzystanie z niego: Załóżmy, że mamy te funkcje do obliczania a
i b
:
func calca() int { return 3 }
func calcb() int { return 4 }
Następnie:
i := If(someCondition).Fint(calca, calcb)
Na przykład warunkiem jest bieżący rok> 2020:
i := If(time.Now().Year() > 2020).Fint(calca, calcb)
Jeśli chcemy użyć literałów funkcyjnych:
i := If(time.Now().Year() > 2020).Fint(
func() int { return 3 },
func() int { return 4 },
)
Uwaga końcowa: jeśli miałbyś funkcje z różnymi podpisami, nie możesz ich tutaj użyć. W takim przypadku możesz użyć literału funkcji z pasującym podpisem, aby nadal mieć zastosowanie.
Na przykład jeśli calca()
i calcb()
miałby również parametry (oprócz wartości zwracanej):
func calca2(x int) int { return 3 }
func calcb2(x int) int { return 4 }
Oto jak możesz ich użyć:
i := If(time.Now().Year() > 2020).Fint(
func() int { return calca2(0) },
func() int { return calcb2(0) },
)
Wypróbuj te przykłady na Go Playground .