if w Go nie ma nawiasów wokół warunku, zawsze wymaga klamer i może zaczynać się od krótkiej instrukcji, która deklaruje zmienne o zasięgu ograniczonym do tego if.
Warunki są sprawdzane od góry i wykonuje się pierwsza prawdziwa gałąź. else if i else są opcjonalne.
Zasady składni
Trzy zasady różnią się od C, Javy i JavaScriptu:
- Brak nawiasów wokół warunku.
if (x > 5)się kompiluje, alegofmtusuwa nawiasy. - Klamry są obowiązkowe, nawet dla jednej instrukcji. Nie istnieje
if x > 5 returnbez klamer. elsestoi w tej samej linii co klamra zamykająca. Go wstawia średnik po}na końcu linii, więc to nie działa:
if x > 5 {
fmt.Println("big")
}
else {
fmt.Println("small")
}
syntax error: unexpected keyword else, expected }
Pisz } else { w jednej linii.
Warunek musi być typu bool. Go nie traktuje 0, "" ani nil jako fałszu, więc if count {} i if name {} się nie kompilują. Porównuj jawnie: if count > 0, if name != "", if user != nil.
Łącz warunki przez && (i), || (lub) i ! (nie). Zarówno &&, jak i || działają na skróty, dzięki czemu sprawdzanie nil jest bezpieczne:
if user != nil && user.IsAdmin() {
// user.IsAdmin() is only called when user is not nil
}
if z instrukcją inicjującą
if może wykonać jedną krótką instrukcję przed warunkiem, oddzieloną średnikiem. Zadeklarowane w niej zmienne są widoczne w każdej gałęzi tego if, a nigdzie za nim:
Ten wzorzec trzyma krótkotrwałe zmienne z dala od otaczającego zasięgu. Pojawia się bez przerwy przy odczycie z mapy (v, ok := m[k]), asercjach typu (s, ok := v.(string)) i błędach.
Druga strona medalu: jeśli potrzebujesz wartości za if, zadeklaruj ją wcześniej. Częsty błąd to umieszczenie wyniku w instrukcji inicjującej, a potem próba użycia go niżej.
Idiom if err != nil
Funkcje, które mogą zawieść, zwracają error na końcu. Sprawdź go od razu, obsłuż lub zwróć i kontynuuj szczęśliwą ścieżkę bez wcięcia:
Zwróć uwagę, że po if err != nil { return ... } nie ma else. Styl Go to obsłużyć błąd, zwrócić i zostawić normalny przepływ przy lewym marginesie. Strona o obsłudze błędów opisuje opakowywanie błędów i sprawdzanie ich typów.
Wczesne powroty zamiast zagnieżdżania
Głęboko zagnieżdżone bloki if trudno się czyta. Odwróć warunki i wracaj wcześnie; każde sprawdzenie czyta się wtedy jak strażnik:
// Nested
func canCheckout(u *User, cart *Cart) bool {
if u != nil {
if u.Verified {
if len(cart.Items) > 0 {
return true
}
}
}
return false
}
// Guards
func canCheckout(u *User, cart *Cart) bool {
if u == nil || !u.Verified {
return false
}
if len(cart.Items) == 0 {
return false
}
return true
}
Programiści Go nazywają to trzymaniem szczęśliwej ścieżki przy lewej krawędzi. Lintery, takie jak revive, zgłaszają else po bloku kończącym się return, bo takie else dodaje wcięcie bez żadnej korzyści.
if/else a switch
Długi łańcuch else if, który porównuje jedną wartość z kilkoma przypadkami, czyta się lepiej jako switch. switch bez wyrażenia zastępuje łańcuch if/else if z dowolnymi warunkami:
switch {
case score >= 90:
return "A"
case score >= 80:
return "B"
default:
return "F"
}
Używaj if dla jednej lub dwóch gałęzi, a switch, gdy jest ich trzy lub więcej.
Brak operatora trójargumentowego
Go nie ma cond ? a : b. Przypisz wartość przez if:
label := "odd"
if n%2 == 0 {
label = "even"
}
Strona o operatorze trójargumentowym wyjaśnia dlaczego i pokazuje alternatywy.
Częste błędy
- Przesłanianie przez :=.
if x, err := f(); err == nil { ... }deklaruje nowextylko dlaif. Zewnętrznexnie zostaje zaktualizowane. - Przypisanie w warunku.
if x = 5 {}to błąd kompilacji (cannot use assignment x = 5 as value), a nie cichy błąd jak w C. Użyj==. - Porównywanie liczb zmiennoprzecinkowych przez ==.
if total == 0.3zawodzi dla obliczonych wartości. Porównuj z tolerancją. - Sprawdzanie niewłaściwego błędu. Po
a, err := f()ib, err := g()upewnij się, że każdeif err != nilstoi zaraz po swoim wywołaniu.
Najczęściej zadawane pytania
Jak napisać if else w Go?
Bez nawiasów wokół warunku i zawsze z klamrami:
if x > 10 {
fmt.Println("big")
} else if x > 5 {
fmt.Println("medium")
} else {
fmt.Println("small")
}
else musi być w tej samej linii co klamra zamykająca poprzedni blok.
Czym jest if z instrukcją inicjującą w Go?
To krótka instrukcja przed warunkiem, oddzielona średnikiem: if n, err := strconv.Atoi(s); err != nil { ... }. Zadeklarowane w niej zmienne istnieją tylko wewnątrz if i jego gałęzi else if oraz else, dzięki czemu nie wyciekają do reszty funkcji.
Czy w Go można napisać if w jednej linii?
Nie bez klamer. if ok return i if (ok) x = 1; to błędy składni. Najkrótsza forma to if ok { return }, a gofmt przenosi ciało do osobnej linii. Go nie ma też operatora trójargumentowego, więc wartość zależna od warunku wymaga if/else albo małej funkcji pomocniczej.
Dlaczego w Go wszędzie jest if err != nil?
Go nie ma wyjątków. Funkcje, które mogą zawieść, zwracają error jako ostatni wynik, a kod wywołujący od razu go sprawdza przez if err != nil. To powtarzanie jest ceną za to, że każde miejsce możliwej awarii jest widoczne tam, gdzie występuje.